对用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