From b83e30b6457db1c3f791e0c3e8a78b316edb4a82 Mon Sep 17 00:00:00 2001 From: rdb Date: Fri, 12 Jun 2009 13:47:49 +0000 Subject: [PATCH] Add support for more TexGen modes --- panda/src/pgraphnodes/shaderGenerator.cxx | 167 ++++++++++++++-------- panda/src/pgraphnodes/shaderGenerator.h | 5 +- 2 files changed, 109 insertions(+), 63 deletions(-) diff --git a/panda/src/pgraphnodes/shaderGenerator.cxx b/panda/src/pgraphnodes/shaderGenerator.cxx index df52205565..c4d1848830 100644 --- a/panda/src/pgraphnodes/shaderGenerator.cxx +++ b/panda/src/pgraphnodes/shaderGenerator.cxx @@ -182,6 +182,10 @@ analyze_renderstate(const RenderState *rs) { _out_aux_normal = (outputs & AuxBitplaneAttrib::ABO_aux_normal) ? true:false; _out_aux_glow = (outputs & AuxBitplaneAttrib::ABO_aux_glow) ? true:false; _out_aux_any = (_out_aux_normal || _out_aux_glow); + + if (_out_aux_normal) { + _need_eye_normal = true; + } // Count number of textures. @@ -257,8 +261,19 @@ analyze_renderstate(const RenderState *rs) { _map_height_in_alpha = true; } if (tex_gen->has_stage(stage)) { - if (tex_gen->get_mode(stage) == TexGenAttrib::M_world_position) { - _need_worldspace_pos = true; + switch (tex_gen->get_mode(stage)) { + case TexGenAttrib::M_world_position: + _need_world_position = true; + break; + case TexGenAttrib::M_world_normal: + _need_world_normal = true; + break; + case TexGenAttrib::M_eye_position: + _need_eye_position = true; + break; + case TexGenAttrib::M_eye_normal: + _need_eye_normal = true; + break; } } } @@ -267,6 +282,8 @@ analyze_renderstate(const RenderState *rs) { if (la->get_num_on_lights() > 0) { _lighting = true; + _need_eye_position = true; + _need_eye_normal = true; } // Find the material. @@ -363,7 +380,7 @@ analyze_renderstate(const RenderState *rs) { const ClipPlaneAttrib *clip_plane = DCAST(ClipPlaneAttrib, rs->get_attrib_def(ClipPlaneAttrib::get_class_slot())); _num_clip_planes = clip_plane->get_num_on_planes(); if (_num_clip_planes > 0) { - _need_worldspace_pos = true; + _need_world_position = true; } // Check for unimplemented features and issue warnings. @@ -408,8 +425,11 @@ clear_analysis() { _out_aux_glow = false; _out_aux_any = false; _material = (Material*)NULL; - _need_worldspace_pos = false; _need_material_props = false; + _need_world_position = false; + _need_world_normal = false; + _need_eye_position = false; + _need_eye_normal = false; _alights.clear(); _dlights.clear(); _plights.clear(); @@ -541,9 +561,7 @@ synthesize_shader(const RenderState *rs) { // These variables will hold the results of register allocation. - char *pos_freg = 0; char *normal_vreg = 0; - char *normal_freg = 0; char *ntangent_vreg = 0; char *ntangent_freg = 0; char *nbinormal_vreg = 0; @@ -553,6 +571,10 @@ synthesize_shader(const RenderState *rs) { pvector texcoord_vreg; pvector texcoord_freg; pvector tslightvec_freg; + char *world_position_freg = 0; + char *world_normal_freg = 0; + char *eye_position_freg = 0; + char *eye_normal_freg = 0; if (_vertex_colors) { _vcregs_used = 1; @@ -580,10 +602,31 @@ synthesize_shader(const RenderState *rs) { text << "\t in float4 vtx_color : COLOR,\n"; text << "\t out float4 l_color : COLOR,\n"; } - if (_need_worldspace_pos > 0) { - text << "\t out float4 l_worldpos,\n"; + if (_need_world_position || _need_world_normal) { text << "\t uniform float4x4 trans_model_to_world,\n"; } + if (_need_world_position) { + world_position_freg = alloc_freg(); + text << "\t out float4 l_world_position : " << world_position_freg << ",\n"; + } + if (_need_world_normal) { + world_normal_freg = alloc_freg(); + text << "\t out float4 l_world_normal : " << world_normal_freg << ",\n"; + } + if (_need_eye_position) { + text << "\t uniform float4x4 trans_model_to_view,\n"; + eye_position_freg = alloc_freg(); + text << "\t out float4 l_eye_position : " << eye_position_freg << ",\n"; + } + if (_need_eye_normal) { + eye_normal_freg = alloc_freg(); + text << "\t uniform float4x4 tpose_view_to_model,\n"; + text << "\t out float4 l_eye_normal : " << eye_normal_freg << ",\n"; + } + if (_map_index_height >= 0 || _need_world_normal || _need_eye_normal) { + normal_vreg = alloc_vreg(); + text << "\t in float4 vtx_normal : " << normal_vreg << ",\n"; + } if (_map_index_height >= 0) { htangent_vreg = alloc_vreg(); hbinormal_vreg = alloc_vreg(); @@ -596,17 +639,7 @@ synthesize_shader(const RenderState *rs) { text << "\t uniform float4 mspos_view,\n"; text << "\t out float3 l_eyevec,\n"; } - if (_map_index_height >= 0 || _lighting) { - normal_vreg = alloc_vreg(); - text << "\t in float4 vtx_normal : " << normal_vreg << ",\n"; - } if (_lighting) { - pos_freg = alloc_freg(); - normal_freg = alloc_freg(); - text << "\t uniform float4x4 trans_model_to_view,\n"; - text << "\t uniform float4x4 tpose_view_to_model,\n"; - text << "\t out float4 l_normal : " << normal_freg << ",\n"; - text << "\t out float4 l_pos : " << pos_freg << ",\n"; if (_map_index_normal >= 0) { // If we had a height map and it used the same stage, that means we already have those inputs. if (_map_index_normal != _map_index_height) { @@ -634,12 +667,6 @@ synthesize_shader(const RenderState *rs) { } } } - } else if (_out_aux_normal) { - normal_vreg = alloc_vreg(); - normal_freg = alloc_freg(); - text << "\t uniform float4x4 tpose_view_to_model,\n"; - text << "\t in float4 vtx_normal : " << normal_vreg << ",\n"; - text << "\t out float4 l_normal : " << normal_freg << ",\n"; } text << "\t float4 vtx_position : POSITION,\n"; text << "\t out float4 l_position : POSITION,\n"; @@ -647,8 +674,18 @@ synthesize_shader(const RenderState *rs) { text << ") {\n"; text << "\t l_position = mul(mat_modelproj, vtx_position);\n"; - if (_need_worldspace_pos) { - text << "\t l_worldpos = mul(trans_model_to_world, vtx_position);\n"; + if (_need_world_position) { + text << "\t l_world_position = mul(trans_model_to_world, vtx_position);\n"; + } + if (_need_world_normal) { + text << "\t l_world_normal = mul(trans_model_to_world, vtx_normal);\n"; + } + if (_need_eye_position) { + text << "\t l_eye_position = mul(trans_model_to_view, vtx_position);\n"; + } + if (_need_eye_normal) { + text << "\t l_eye_normal.xyz = mul((float3x3)tpose_view_to_model, vtx_normal.xyz);\n"; + text << "\t l_eye_normal.w = 0;\n"; } for (int i=0; i<_num_textures; i++) { if (!tex_gen->has_stage(texture->get_on_stage(i))) { @@ -658,13 +695,6 @@ synthesize_shader(const RenderState *rs) { if (_vertex_colors) { text << "\t l_color = vtx_color;\n"; } - if (_lighting) { - text << "\t l_pos = mul(trans_model_to_view, vtx_position);\n"; - } - if (_lighting || _out_aux_normal) { - text << "\t l_normal.xyz = mul((float3x3)tpose_view_to_model, vtx_normal.xyz);\n"; - text << "\t l_normal.w = 0;\n"; - } if (_lighting && (_map_index_normal >= 0)) { text << "\t l_tangent.xyz = mul((float3x3)tpose_view_to_model, vtx_tangent" << _map_index_normal << ".xyz);\n"; text << "\t l_tangent.w = 0;\n"; @@ -696,8 +726,17 @@ synthesize_shader(const RenderState *rs) { text << "}\n\n"; text << "void fshader(\n"; - if (_need_worldspace_pos) { - text << "\t in float4 l_worldpos,\n"; + if (_need_world_position) { + text << "\t in float4 l_world_position : " << world_position_freg << ",\n"; + } + if (_need_world_normal) { + text << "\t in float4 l_world_normal : " << world_normal_freg << ",\n"; + } + if (_need_eye_position) { + text << "\t in float4 l_eye_position : " << eye_position_freg << ",\n"; + } + if (_need_eye_normal) { + text << "\t in float4 l_eye_normal : " << eye_normal_freg << ",\n"; } const TexMatrixAttrib *tex_matrix = DCAST(TexMatrixAttrib, rs->get_attrib_def(TexMatrixAttrib::get_class_slot())); for (int i=0; i<_num_textures; i++) { @@ -710,18 +749,11 @@ synthesize_shader(const RenderState *rs) { text << "\t uniform float4x4 texmat_" << i << ",\n"; } } - if (_lighting || _out_aux_normal) { - text << "\t in float3 l_normal : " << normal_freg << ",\n"; - } if (_lighting && (_map_index_normal >= 0)) { text << "\t in float3 l_tangent : " << ntangent_freg << ",\n"; text << "\t in float3 l_binormal : " << nbinormal_freg << ",\n"; } if (_lighting) { - text << "\t in float4 l_pos : " << pos_freg << ",\n"; - if (_shadows) { - text << "\t in float4 l_position : " << alloc_freg() << ",\n"; - } for (int i=0; i<(int)_alights.size(); i++) { text << "\t uniform float4 alight_alight" << i << ",\n"; } @@ -781,8 +813,8 @@ synthesize_shader(const RenderState *rs) { text << ") {\n"; // Clipping first! for (int i=0; i<_num_clip_planes; ++i) { - text << "\t if (l_worldpos.x * clipplane_" << i << ".x + l_worldpos.y "; - text << "* clipplane_" << i << ".y + l_worldpos.z * clipplane_" << i << ".z + clipplane_" << i << ".w <= 0) {\n"; + text << "\t if (l_world_position.x * clipplane_" << i << ".x + l_world_position.y "; + text << "* clipplane_" << i << ".y + l_world_position.z * clipplane_" << i << ".z + clipplane_" << i << ".w <= 0) {\n"; text << "\t discard;\n"; text << "\t }\n"; } @@ -796,10 +828,21 @@ synthesize_shader(const RenderState *rs) { if (tex_gen != NULL && tex_gen->has_stage(stage)) { switch (tex_gen->get_mode(stage)) { case TexGenAttrib::M_world_position: - text << "\t float4 l_texcoord" << i << " = l_worldpos;\n"; + text << "\t float4 l_texcoord" << i << " = l_world_position;\n"; + break; + case TexGenAttrib::M_world_normal: + text << "\t float4 l_texcoord" << i << " = l_world_normal;\n"; + break; + case TexGenAttrib::M_eye_position: + text << "\t float4 l_texcoord" << i << " = l_eye_position;\n"; + break; + case TexGenAttrib::M_eye_normal: + text << "\t float4 l_texcoord" << i << " = l_eye_normal;\n"; + text << "\t l_texcoord" << i << ".w = 1.0f;\n"; break; default: pgraph_cat.error() << "Unsupported TexGenAttrib mode\n"; + text << "\t float4 l_texcoord" << i << " = float4(0, 0, 0, 0);\n"; } } if (tex_matrix != NULL && tex_matrix->has_stage(stage)) { @@ -833,18 +876,18 @@ synthesize_shader(const RenderState *rs) { if (_map_index_normal >= 0) { text << "\t // Translate tangent-space normal in map to view-space.\n"; text << "\t float3 tsnormal = ((float3)tex" << _map_index_normal << " * 2) - 1;\n"; - text << "\t l_normal = l_normal * tsnormal.z;\n"; - text << "\t l_normal+= l_tangent * tsnormal.x;\n"; - text << "\t l_normal+= l_binormal * tsnormal.y;\n"; - text << "\t l_normal = normalize(l_normal);\n"; + text << "\t l_eye_normal = l_eye_normal * tsnormal.z;\n"; + text << "\t l_eye_normal+= l_tangent * tsnormal.x;\n"; + text << "\t l_eye_normal+= l_binormal * tsnormal.y;\n"; + text << "\t l_eye_normal = normalize(l_eye_normal);\n"; } else { text << "\t // Correct the surface normal for interpolation effects\n"; - text << "\t l_normal = normalize(l_normal);\n"; + text << "\t l_eye_normal.xyz = normalize(l_eye_normal.xyz);\n"; } } if (_out_aux_normal) { text << "\t // Output the camera-space surface normal\n"; - text << "\t o_aux.rgb = (l_normal.rgb*0.5) + float3(0.5,0.5,0.5);\n"; + text << "\t o_aux.rgb = (l_eye_normal.xyz*0.5) + float3(0.5,0.5,0.5);\n"; } if (_lighting) { text << "\t // Begin view-space light calculations\n"; @@ -887,7 +930,7 @@ synthesize_shader(const RenderState *rs) { text << "\t lcolor = dlight_dlight" << i << "_rel_view[0];\n"; text << "\t lspec = dlight_dlight" << i << "_rel_view[1];\n"; text << "\t lvec = dlight_dlight" << i << "_rel_view[2];\n"; - text << "\t lcolor *= saturate(dot(l_normal, lvec.xyz));\n"; + text << "\t lcolor *= saturate(dot(l_eye_normal, lvec.xyz));\n"; if (_shadows && _dlights[i]->_shadow_caster) { if (_use_shadow_filter) { text << "\t lshad = shadow2DProj(k_dlighttex" << i << ", l_dlightcoord" << i << ").r;\n"; @@ -902,11 +945,11 @@ synthesize_shader(const RenderState *rs) { } if (_have_specular) { if (_material->get_local()) { - text << "\t lhalf = normalize(lvec - normalize(l_pos));\n"; + text << "\t lhalf = normalize(lvec - normalize(l_eye_position));\n"; } else { text << "\t lhalf = dlight_dlight" << i << "_rel_view[3];\n"; } - text << "\t lspec *= pow(saturate(dot(l_normal, lhalf.xyz)), shininess);\n"; + text << "\t lspec *= pow(saturate(dot(l_eye_normal, lhalf.xyz)), shininess);\n"; text << "\t tot_specular += lspec;\n"; } } @@ -916,22 +959,22 @@ synthesize_shader(const RenderState *rs) { text << "\t lspec = plight_plight" << i << "_rel_view[1];\n"; text << "\t lpoint = plight_plight" << i << "_rel_view[2];\n"; text << "\t latten = plight_plight" << i << "_rel_view[3];\n"; - text << "\t lvec = lpoint - l_pos;\n"; + text << "\t lvec = lpoint - l_eye_position;\n"; text << "\t ldist = length(float3(lvec));\n"; text << "\t lvec /= ldist;\n"; text << "\t lattenv = 1/(latten.x + latten.y*ldist + latten.z*ldist*ldist);\n"; - text << "\t lcolor *= lattenv * saturate(dot(l_normal, lvec.xyz));\n"; + text << "\t lcolor *= lattenv * saturate(dot(l_eye_normal, lvec.xyz));\n"; if (_have_diffuse) { text << "\t tot_diffuse += lcolor;\n"; } if (_have_specular) { if (_material->get_local()) { - text << "\t lhalf = normalize(lvec - normalize(l_pos));\n"; + text << "\t lhalf = normalize(lvec - normalize(l_eye_position));\n"; } else { text << "\t lhalf = normalize(lvec - float4(0,1,0,0));\n"; } text << "\t lspec *= lattenv;\n"; - text << "\t lspec *= pow(saturate(dot(l_normal, lhalf.xyz)), shininess);\n"; + text << "\t lspec *= pow(saturate(dot(l_eye_normal, lhalf.xyz)), shininess);\n"; text << "\t tot_specular += lspec;\n"; } } @@ -942,14 +985,14 @@ synthesize_shader(const RenderState *rs) { text << "\t lpoint = slight_slight" << i << "_rel_view[2];\n"; text << "\t ldir = slight_slight" << i << "_rel_view[3];\n"; text << "\t latten = satten_slight" << i << ";\n"; - text << "\t lvec = lpoint - l_pos;\n"; + text << "\t lvec = lpoint - l_eye_position;\n"; text << "\t ldist = length(float3(lvec));\n"; text << "\t lvec /= ldist;\n"; text << "\t langle = saturate(dot(ldir.xyz, lvec.xyz));\n"; text << "\t lattenv = 1/(latten.x + latten.y*ldist + latten.z*ldist*ldist);\n"; text << "\t lattenv *= pow(langle, latten.w);\n"; text << "\t if (langle < ldir.w) lattenv = 0;\n"; - text << "\t lcolor *= lattenv * saturate(dot(l_normal, lvec.xyz));\n"; + text << "\t lcolor *= lattenv * saturate(dot(l_eye_normal, lvec.xyz));\n"; if (_shadows && _slights[i]->_shadow_caster) { if (_use_shadow_filter) { text << "\t lshad = shadow2DProj(k_slighttex" << i << ", l_slightcoord" << i << ").r;\n"; @@ -965,12 +1008,12 @@ synthesize_shader(const RenderState *rs) { } if (_have_specular) { if (_material->get_local()) { - text << "\t lhalf = normalize(lvec - normalize(l_pos));\n"; + text << "\t lhalf = normalize(lvec - normalize(l_eye_position));\n"; } else { text << "\t lhalf = normalize(lvec - float4(0,1,0,0));\n"; } text << "\t lspec *= lattenv;\n"; - text << "\t lspec *= pow(saturate(dot(l_normal, lhalf.xyz)), shininess);\n"; + text << "\t lspec *= pow(saturate(dot(l_eye_normal, lhalf.xyz)), shininess);\n"; text << "\t tot_specular += lspec;\n"; } } diff --git a/panda/src/pgraphnodes/shaderGenerator.h b/panda/src/pgraphnodes/shaderGenerator.h index aa8f355cde..3bddfb16ca 100644 --- a/panda/src/pgraphnodes/shaderGenerator.h +++ b/panda/src/pgraphnodes/shaderGenerator.h @@ -135,8 +135,11 @@ protected: int _num_clip_planes; bool _use_shadow_filter; - bool _need_worldspace_pos; bool _need_material_props; + bool _need_world_position; + bool _need_world_normal; + bool _need_eye_position; + bool _need_eye_normal; void analyze_renderstate(const RenderState *rs); void clear_analysis();