对用OpenGL ES 2.0实现OpenGL ES 1.1的顶点着色器的研究

对用OpenGL ES 2.0实现OpenGL ES 1.1的顶点着色器的研究

想要彻底研究OpenGL ES 2.0与前一代OpenGL的区别,还是要费很大一番精力的。最近在仔细研读《OpenGL ES 2.0 Programming Guide》,虽然这本书最早出版日期是2008年,距今已经7年了,而著作的日期或许还要早上半年到1年,但是目前OpenGL ES 2.0是主流三维开发框架,因此这本书的知识直到现在,依然受用。

OpenGL ES 2.0是桌面版OpenGL 2.0的一个子集,它清除了一些冗余并且难以实现的API,只保留简单的部分,这样让硬件实现变得容易起来。而OpenGL ES 2.0对于上层的开发者来说,几乎没有什么变化,只要会写着色器,会玩转OpenGL 2.0,那么我想OpenGL ES 2.0自然也不在话下。

在OpenGL ES 1.1或者是OpenGL 1.5及以下中,光照和变换(T&L)部分是通过固定渲染管线来操作的,也就是说,相关数据结构已经填好,只需要自己填充主要的部分就好了。但是到了OpenGL ES 2.0,由于去掉了固定渲染管线,开发者需要自己设计渲染框架,一切渲染的手法都由开发者来完成,这虽然提高了要求,但是增加了自由度,开发者可以利用知识写出精简的渲染方法出来。

而通过OpenGL ES 2.0模拟出OpenGL ES 1.1的渲染管线也是可以的,《OpenGL ES 2.0 Programming Guide》一书中就使用顶点着色器实现了相关的方法。最近我在研究这样的着色器,为了以后备忘参考,将该着色器贴出来,并且附上我的部分注释。

//******************************************************************
//
// OpenGL ES 2.0 vertex shader that implements the following
// OpenGL ES 1.1 fixed function pipeline
//
// - compute lighting equation for up to eight directional/point/
// - spot lights
// - transform position to clip coordinates
// - texture coordinate transforms for up to two texture coordinates
// - compute fog factor
// - compute user clip plane dot product (stored as v_ucp_factor)
//
//******************************************************************
#define NUM_TEXTURES 2
#define GLI_FOG_MODE_LINEAR 0
#define GLI_FOG_MODE_EXP 1
#define GLI_FOG_MODE_EXP2 2
struct light// 光源的结构体
{
    vec4 position; // light position for a point/spot light or
    // normalized dir. for a directional light
    vec4 ambient_color;
    vec4 diffuse_color;
    vec4 specular_color;
    vec3 spot_direction;
    vec3 attenuation_factors;
    float spot_exponent;
    float spot_cutoff_angle;
    bool compute_distance_attenuation;
};
struct material// 材质的结构体
{
    vec4 ambient_color;
    vec4 diffuse_color;
    vec4 specular_color;
    vec4 emissive_color;
    float specular_exponent;
};

// 一些属性
const float c_zero = 0.0;
const float c_one = 1.0;
const int indx_zero = 0;
const int indx_one = 1;

uniform mat4 mvp_matrix; // combined model-view +
// projection matrix
uniform mat4 modelview_matrix; // model view matrix
uniform mat3 inv_modelview_matrix; // inverse model-view

// matrix used
// to transform normal
uniform mat4 tex_matrix[NUM_TEXTURES]; // texture matrices
uniform bool enable_tex[NUM_TEXTURES]; // texture enables
uniform bool enable_tex_matrix[NUM_TEXTURES]; // texture matrix

// enables
uniform material material_state;
uniform vec4 ambient_scene_color;
uniform light light_state[8];
uniform bool light_enable_state[8]; // booleans to indicate
// which of eight
// lights are enabled

uniform int num_lights;// number of lights enabled = sum of
// light_enable_state bools set to TRUE
uniform bool enable_lighting; // is lighting enabled
uniform bool light_model_two_sided; // is two-sided lighting
// enabled

uniform bool enable_color_material; // is color material
// enabled

uniform bool enable_fog; // is fog enabled
uniform float fog_density;
uniform float fog_start, fog_end;
uniform int fog_mode; // fog mode - linear, exp,

// or exp2
uniform bool xform_eye_p; // xform_eye_p is set if we need

// Peye for user clip plane,
// lighting, or fog
uniform bool rescale_normal; // is rescale normal enabled
uniform bool normalize_normal; // is normalize normal enabled
uniform float rescale_normal_factor; // rescale normal factor if
// glEnable(GL_RESCALE_NORMAL)

uniform vec4 ucp_eqn; // user clip plane equation –
// - one user clip plane specified

uniform bool enable_ucp; // is user clip plane enabled
//******************************************************
// vertex attributes - not all of them may be passed in
//******************************************************
attribute vec4 a_position; // this attribute is always specified
attribute vec4 a_texcoord0;// available if enable_tex[0] is true
attribute vec4 a_texcoord1;// available if enable_tex[1] is true
attribute vec4 a_color; // available if !enable_lighting or
// (enable_lighting && enable_color_material)

attribute vec3 a_normal; // available if xform_normal is set
// (required for lighting)
//************************************************
// varying variables output by the vertex shader
//************************************************
varying vec4 v_texcoord[NUM_TEXTURES];
varying vec4 v_front_color;
varying vec4 v_back_color;
varying float v_fog_factor;
varying float v_ucp_factor;
//************************************************
// temporary variables used by the vertex shader
//************************************************
vec4 p_eye;
vec3 n;
vec4 mat_ambient_color;
vec4 mat_diffuse_color;

vec4
lighting_equation(int i)// 针对光照做一系列公式运算
{
    vec4 computed_color = vec4(c_zero, c_zero, c_zero, c_zero);
    vec3 h_vec;
    float ndotl, ndoth;
    float att_factor;
    att_factor = c_one;
    vec3 VPpli;// 视点到光源的向量(view point to light)
    if(light_state[i].position.w != c_zero)
    {
        float spot_factor;
        vec3 att_dist;
        // this is a point or spot light
        // we assume "w" values for PPli and V are the same
        VPpli = light_state[i].position.xyz - p_eye.xyz;
        if(light_state[i].compute_distance_attenuation)// 计算衰减
        {
            // compute distance attenuation
            att_dist.x = c_one;
            att_dist.z = dot(VPpli, VPpli);
            att_dist.y = sqrt(att_dist.z);
            att_factor = c_one / dot(att_dist,
                                     light_state[i].attenuation_factors);
        }
        VPpli = normalize(VPpli);// 归一化
        if(light_state[i].spot_cutoff_angle < 180.0)// 计算聚光灯的半角内的光照
        {
            // compute spot factor
            spot_factor = dot(-VPpli, light_state[i].spot_direction);
            if(spot_factor >= cos(radians(
                                      light_state[i].spot_cutoff_angle)))
                spot_factor = pow(spot_factor,
                                  light_state[i].spot_exponent);
            else
                spot_factor = c_zero;
            att_factor *= spot_factor;
        }
    }
    else
    {
        // directional light
        VPpli = light_state[i].position.xyz;
    }
    if(att_factor > c_zero)
    {
        // process lighting equation --> compute the light color
        computed_color += (light_state[i].ambient_color *
                           mat_ambient_color);// 计算环境光
        ndotl = max(c_zero, dot(n, VPpli));
        computed_color += (ndotl * light_state[i].diffuse_color *
                           mat_diffuse_color);// 计算漫反射光
        h_vec = normalize(VPpli + vec3(c_zero, c_zero, c_one));
        ndoth = dot(n, h_vec);
        if (ndoth > c_zero)// 计算镜面反射
        {
            computed_color += (pow(ndoth,
                                   material_state.specular_exponent) *
                               material_state.specular_color *
                               light_state[i].specular_color);
        }
        computed_color *= att_factor; // multiply color with
        // computed attenuation factor
        // * computed spot factor
    }
    return computed_color;
}
float
compute_fog()// 计算雾
{
    float f;
    // use eye Z as approximation
    if(fog_mode == GLI_FOG_MODE_LINEAR)
    {
        f = (fog_end - p_eye.z) / (fog_end - fog_start);
    }
    else if(fog_mode == GLI_FOG_MODE_EXP)
    {
        f = exp(-(p_eye.z * fog_density));
    }
    else
    {
        f = (p_eye.z * fog_density);
        f = exp(-(f * f));
    }
    f = clamp(f, c_zero, c_one);
    return f;
}

vec4
do_lighting()// 计算总光照
{
    vec4 vtx_color;
    int i, j;
    vtx_color = material_state.emissive_color +
            (mat_ambient_color * ambient_scene_color);
    j = (int)c_zero;
    for (i=(int)c_zero; i<8; i++)
    {
        if(j >= num_lights)
            break;
        if (light_enable_state[i])
        {
            j++;
            vtx_color += lighting_equation(i);
        }
    }
    vtx_color.a = mat_diffuse_color.a;
    return vtx_color;
}

void
main(void)// 入口函数
{
    int i, j;
    // do we need to transform P
    if(xform_eye_p)
        p_eye = modelview_matrix * a_position;
    if(enable_lighting)
    {
        n = inv_modelview_matrix * a_normal;// 这样的model view通常需要需要求逆
        if(rescale_normal)// 如果涉及到了缩放,那么要缩放
            n = rescale_normal_factor * n;// 这样就达到了求法线矩阵的目的
        if (normalize_normal)
            n = normalize(n);
        mat_ambient_color = enable_color_material ? a_color
                                                  : material_state.ambient_color;
        mat_diffuse_color = enable_color_material ? a_color
                                                  : material_state.diffuse_color;
        v_front_color = do_lighting();// 对正面执行光照
        v_back_color = v_front_color;
        // do 2-sided lighting
        if(light_model_two_sided)
        {
            n = -n;
            v_back_color = do_lighting();
        }
    }
    else
    {
        // set the default output color to be the per-vertex /
        // per-primitive color
        v_front_color = a_color;
        v_back_color = a_color;
    }
    // do texture xforms
    v_texcoord[indx_zero] = vec4(c_zero, c_zero, c_zero, c_one);
    if(enable_tex[indx_zero])
    {
        if(enable_tex_matrix[indx_zero])
            v_texcoord[indx_zero] = tex_matrix[indx_zero] *
                    a_texcoord0;
        else
            v_texcoord[indx_zero] = a_texcoord0;
    }
    v_texcoord[indx_one] = vec4(c_zero, c_zero, c_zero, c_one);
    if(enable_tex[indx_one])
    {
        if(enable_tex_matrix[indx_one])
            v_texcoord[indx_one] = tex_matrix[indx_one] * a_texcoord1;
        else
            v_texcoord[indx_one] = a_texcoord1;
    }
    v_ucp_factor = enable_ucp ? dot(p_eye, ucp_eqn) : c_zero;
    v_fog_factor = enable_fog ? compute_fog() : c_one;
    gl_Position = mvp_matrix * a_position;// 计算最终的位置
}
时间: 2024-10-07 05:31:28

对用OpenGL ES 2.0实现OpenGL ES 1.1的顶点着色器的研究的相关文章

基于Cocos2d-x学习OpenGL ES 2.0系列——OpenGL ES渲染之Shader准备(7)

Cocos2d-x底层图形绘制是使用OpenGL ES协议的.OpenGL ES是什么呢? OpenGL ES(OpenGl for Embedded System)是OpenGL三维图形API的子集,针对手机.Pad和游戏主机等嵌入式设备而设计.该API由Khronos集团定义推广,Khronos是一个图形软硬件行业协会,该协会主要关注图形和多媒体方面的开放标准.OpenGL ES是OpenGL三维图形API的子集,针对手机.Pad和游戏主机等嵌入式设备而设计.Cocos2d-x底层图形渲染使

OpenGL ES 3.0顶点着色器(二)

#version 300 es uniform mat4 u_mvpMatrix; in vec4 a_position; in vec4 a_color;out vec4 v_color;void main() { v_color = a_color; gl_Position = u_mvpMatrix * a_position; } 上面是一段顶点着色器代码. #version 300 es 出现在顶点着色文件的第一行,说明着色语言版本是3.0(shading language 3.0) u

OpenGL ES 2.0 顶点着色器的妙用

1.飘扬的旗帜(水面起伏) 基本原理 绘制一帧画面时由顶点着色器根据一定的规则变换各个顶点的位置,即可得到旗帜迎风飘扬的效果. 为了使旗帜的飘动过程比较平滑,采用基于正弦曲线的顶点位置变换规则. 计算方法 传入顶点着色器的原始顶点的Z{X|Y|Z}坐标都是相同的(本案例为0),经过顶点着色器变换后顶点的Z{X|Y|Z}坐标是根据正弦曲线分布的 首先计算出当前处理顶点的X坐标与最左侧顶点X坐标的差值,即X距离 然后根据距离与角度的换算率将X距离换算为当前顶点与最左侧顶点的角度差(tempAngle

OpenGL学习随笔(四)-- 顶点着色器(VertexShader)

顶点着色器对顶点实现了一种通用的可编程方法. 顶点着色器的输入数据由下面组成: Attributes:使用顶点数组封装每个顶点的数据,一般用于每个顶点都各不相同的变量,如顶点位置.颜色等. Uniforms:顶点着色器使用的常量数据,不能被着色器修改,一般用于对同一组顶点组成的单个3D物体中所有顶点都相同的变量,如当前光源的位置. Samplers:这个是可选的,一种特殊的uniforms,表示顶点着色器使用的纹理. Shader program:顶点着色器的源码或可执行文件,描述了将对顶点执行

基于Cocos2d-x学习OpenGL ES 2.0系列——OpenGL ES渲染之LayerColor(8)

在前面文章中讲述了Cocos2d-x引擎OpenGL渲染准备Shader方面,本文主要讲解使用LayerColor来讲述OpenGL的渲染过程. 1.LayerColor对象创建 添加LayerColor元素到游戏中: autolayerColor = LayerColor::create(Color4B(255, 0, 0, 255), 100, 100); layerColor->setPosition(100,100); 下面是LayerColor::create方法: LayerColo

OpenGL ES 2.0渲染管线

http://codingnow.cn/opengles/1504.html Opengl es 2.0实现了可编程的图形管线,比起1.x的固定管线要复杂和灵活很多,由两部分规范组成:Opengl es 2.0 API规范和Opengl es着色语言规范.下图是Opengl es 2.0渲染管线,阴影部分是opengl es 2.0的可编程阶段. 1. 顶点着色器(VertexShader) 顶点着色器对顶点实现了一种通用的可编程方法. 顶点着色器的输入数据由下面组成: Attributes:使

OpenGL ES着色器语言之语句和结构体(官方文档第六章)内建变量(官方文档第七、八章)

OpenGL ES着色器语言之语句和结构体(官方文档第六章) OpenGL ES着色器语言的程序块基本构成如下: 语句和声明 函数定义 选择(if-else) 迭代(for, while, do-while) 跳跃(discard, return, break, continue) 6.1函数定义   着色器是由一系列全局声明和函数定义组成的.函数声明规范如下: // prototype returnType functionName (type0 arg0, type1 arg1, ...,

OpenGL ES 3.0之Uniform详解

Uniform是变量类型的一种修饰符,是OpenGL ES  中被着色器中的常量值,使用存储各种着色器需要的数据,例如:转换矩阵.光照参数或者颜色. uniform 的空间被顶点着色器和片段着色器分享.也就是说顶点着色器和片段着色器被链接到一起进入项目,它们分享同样的uniform.因此一个在顶点着色器中声明的uniform,相当于在片段着色器中也声明过了.当应用程序装载uniform 时,它的值在顶点着色器和片段着色器都可用.在链接阶段,链接器将分配常量在项目里的实际地址,那个地址是被应用程序

OpenGL ES 3.0之VertexAttributes,Vertex Arrays,and Buffer Objects(九)

顶点数据,也称为顶点属性,指每一个顶点数据.指能被用来描述每个顶点的数据,或能被所有顶点使用的常量值.例如你想绘制一个具有颜色的立方体三角形.你指定一个恒定的值用于三角形的所有三个顶点颜色.但三角形的三个顶点位置是不同的,你需要指定一个顶点矩阵存储三个位置值. 指定顶点属性数据 顶点属性数据可以使用顶点数组或常量值指定每个顶点数据,OpenGL ES 3.0 必须至少支持16 个顶点属性.应用应该能够查询编译器支持的确切属性数.下面的程序指出如何查询. GLint maxVertexAttrib