###============================================================================== # Doom 3 Interaction Vertex/Fragment Program # # Blinn-Phong Lighting Model (Isotropic) ###============================================================================== # # -------------------------------------- # input: # # attrib[8] = texture coordinates # attrib[9] = global tangent # attrib[10] = global bitangent # attrib[11] = global normal # # env[0] = diffuse modifier # env[1] = specular modifier # env[2] = ? # env[3] = ? # env[4] = localLightOrigin # env[5] = localViewOrigin # env[6] = lightProjection S # env[7] = lightProjection T # env[8] = lightProjection Q # env[9] = lightFalloff S # env[10] = bumpMatrix S # env[11] = bumpMatrix T # env[12] = diffuseMatrix S # env[13] = diffuseMatrix T # env[14] = specularMatrix S # env[15] = specularMatrix T # env[16] = vertex color modulate # env[17] = vertex color add # #-------------------------------------- # output: # # texture 0 = normalization cube map # texture 1 = per-surface normal map # texture 2 = 1D light falloff texture # texture 3 = 2D light projection texture # texture 4 = per-surface diffuse map # texture 5 = per-surface specular map # texture 6 = specular lookup table # #-------------------------------------- ###============================================================================== !!ARBvp1.0 OPTION ARB_position_invariant; # Instruction Count: 25 PARAM defaultTexCoord = { 0.0, 0.5, 0.0, 1.0 }; PARAM dirFromSky = { 0.0, 0.0, 1.0 }; TEMP R0; # world space light vector ADD R0, program.env[4], -vertex.position; # put into texture space for TEX0 DP3 result.texcoord[0].x, vertex.attrib[9], R0; DP3 result.texcoord[0].y, vertex.attrib[10], R0; DP3 result.texcoord[0].z, vertex.attrib[11], R0; # texture 1 takes the base coordinates by the texture matrix MOV result.texcoord[1], defaultTexCoord; DP4 result.texcoord[1].x, vertex.attrib[8], program.env[10]; DP4 result.texcoord[1].y, vertex.attrib[8], program.env[11]; # texture 2 has three texgens (cubemap projection) DP4 result.texcoord[2].x, vertex.position, program.env[6]; DP4 result.texcoord[2].y, vertex.position, program.env[7]; DP4 result.texcoord[2].z, vertex.position, program.env[9]; DP4 result.texcoord[2].w, vertex.position, program.env[8]; # tangent space -> world space conversion matrix DP3 result.texcoord[3].x, vertex.attrib[9], program.env[6]; DP3 result.texcoord[3].y, vertex.attrib[10], program.env[6]; DP3 result.texcoord[3].z, vertex.attrib[11], program.env[6]; DP3 result.texcoord[4].x, vertex.attrib[9], program.env[7]; DP3 result.texcoord[4].y, vertex.attrib[10], program.env[7]; DP3 result.texcoord[4].z, vertex.attrib[11], program.env[7]; DP3 result.texcoord[5].x, vertex.attrib[9], program.env[9]; DP3 result.texcoord[5].y, vertex.attrib[10], program.env[9]; DP3 result.texcoord[5].z, vertex.attrib[11], program.env[9]; # world space view vector ADD R0, program.env[5], -vertex.position; # put into texture space for TEX6 DP3 result.texcoord[6].x, vertex.attrib[9], R0; DP3 result.texcoord[6].y, vertex.attrib[10], R0; DP3 result.texcoord[6].z, vertex.attrib[11], R0; # move world space view vector to TEX7 DP3 result.texcoord[7].x, vertex.attrib[9], dirFromSky; DP3 result.texcoord[7].y, vertex.attrib[10], dirFromSky; DP3 result.texcoord[7].z, vertex.attrib[11], dirFromSky; # MOV result.texcoord[7], R0; # generate the vertex color, which can be 1.0, color, or 1.0 - color # for 1.0 : env[16] = 0.0, env[17] = 1.0 # for color : env[16] = 1.0, env[17] = 0.0 # for 1.0 - color : env[16] = -1.0, env[17] = 1.0 MAD result.color, vertex.color, program.env[16], program.env[17]; END #================================================================================== !!ARBfp1.0 OPTION ARB_precision_hint_fastest; # Instruction Count: ALU: 56 TEX: 6 Total: 88 OUTPUT oColor = result.color; ATTRIB vColor = fragment.color; ATTRIB lightVecTS = fragment.texcoord[0]; ATTRIB defaultTC = fragment.texcoord[1]; ATTRIB lightProjTC = fragment.texcoord[2]; ATTRIB tangent = fragment.texcoord[3]; ATTRIB bitangent = fragment.texcoord[4]; ATTRIB normal = fragment.texcoord[5]; ATTRIB viewVecTS = fragment.texcoord[6]; ATTRIB viewVecWS = fragment.texcoord[7]; PARAM lightColor = program.env[0]; PARAM specColor = program.env[1]; PARAM const = { 1.0, 2.0, 4.0, 5.0 }; PARAM const2 = { 0.25, 0.5, 0.75, 0.75 }; PARAM lumVec = { 0.212671, 0.715160, 0.072169 }; # Scale the normal map scale up by a factor of 1.5. PARAM subOne = { -1.4, -1.4, -1.0, -1.0 }; PARAM scaleTwo = { 2.8, 2.8, 2.0, 2.0 }; #PARAM subOneN = { -1.0, -1.0, -1.0, -1.0 }; #PARAM scaleTwoN = { 2.0, 2.0, 2.0, 2.0 }; PARAM half = { 0.5, 0.5, 0.5, 0.5 }; #--------------------------------------------------------- # Regardless of the name, the fresnel parameters have diverse usage. # Note that, some multipliers are really insane values, # this enable us to utilize High Dynamic Range #--------------------------------------------------------- # Pramaeters are, respectively: unsused, (1 - RI) specular correction, rimcontrib, unused #--------------------------------------------------------- PARAM fresnelParms = { 1.0, .23, .5, 1.0 }; #spec correc. 30 #--------------------------------------------------------- #--------------------------------------------------------- # Pramaeters are, respectively: Unsused, RI + spec correction, specular multiplier, rim power; #--------------------------------------------------------- PARAM fresnelParms2 = { .2, .023, 120.0, 4.0 }; # SPEC MUL WAS 200, 350, 120 #--------------------------------------------------------- # Pramaeters are, respectively: ambient rim scale, diffuse rim scale, min. spec exp, max spec exp; #--------------------------------------------------------- PARAM lightParms = { .7, 1.8, 10.0, 30.0 }; ## rim 4.4, 0.8 PARAM cubemapLookupVec = { 0.33333, 0.33333, 0.33333 }; PARAM colGround = { .35, .32, .32, 1.0 }; PARAM colSky = { .88, .88, .88, 1.0 }; #--------------------------------------------------------- #--------------------------------------------------------- TEMP fresnelTerm, rimLight; #--------------------------------------------------------- TEMP lightVec, viewVec, normalVec, halfVec, reflectVec, wViewVec, wNormalVec; TEMP diffuse, specular, gloss, color, ambient, dirSky; TEMP light, atten, fresnel, pos, lightCube, lightProj; TEMP NdotL, NdotV, NdotH; TEMP R1, R2, R3; TEMP C1, C2, C3; # calculate point light tc MAD R1.xyz, lightProjTC, 2.0, -1.0; # calculate projected light tc MOV R2, lightProjTC; MOV R2.z, -1.0; RCP R2.w, lightProjTC.w; MUL R2.xy, R2, R2.w; MAD R2.xy, R2, 2.0, -1.0; # sample projection cube map TEX lightCube, R1, texture[3], CUBE; TEX lightProj, R2, texture[3], CUBE; # calculate attenuation (x = point, y = projected) DP3 R1.x, R1, R1; POW R1.x, R1.x, 0.5.x; MOV R1.y, lightProjTC.z; ADD_SAT R1.xy, 1.0, -R1; MUL R1.xy, R1, R1; MUL lightCube, lightCube, R1.x; MUL lightProj, lightProj, R1.y; # if w > 1.0, light = projected, else light = point SLT R1.w, 1.0, lightProjTC.w; CMP atten, -R1.w, lightProj, lightCube; # early out # DP3 atten.w, atten, atten; # SLT atten.w, atten.w, 0.00001; MOV atten.w, R1.x; # load texture maps TEX ambient, lightProjTC, texture[3], CUBE; TEX normalVec, defaultTC, texture[1], 2D; TEX diffuse, defaultTC, texture[4], 2D; TEX gloss, defaultTC, texture[5], 2D; # normalize world space light vector DP3 lightVec.w, lightVecTS, lightVecTS; RSQ lightVec.w, lightVec.w; MUL lightVec.xyz, lightVecTS, lightVec.w; # normalize tangent space view vector DP3 viewVec.w, viewVecTS, viewVecTS; RSQ viewVec.w, viewVec.w; MUL viewVec.xyz, viewVecTS, viewVec.w; # normalize world space view vector DP3 wViewVec.w, viewVecWS, viewVecWS; RSQ wViewVec.w, wViewVec.w; MUL wViewVec.xyz, viewVecWS, wViewVec.w; # calculate the half angle vector and normalize ADD halfVec, lightVec, viewVec; DP3 halfVec.w, halfVec, halfVec; RSQ halfVec.w, halfVec.w; MUL halfVec.xyz, halfVec, halfVec.w; # scale tangent space normal vector to -1.0<->1.0 range # MAD normalVec.xyz, normalVec.wyzx, const.y, -const.x; MOV normalVec.x, normalVec.a; MAD normalVec.xyz, normalVec, scaleTwo, subOne; # transform tangent space normal vector into world space DP3 wNormalVec.x, normalVec, tangent; DP3 wNormalVec.y, normalVec, bitangent; DP3 wNormalVec.z, normalVec, normal; # normalize tangent space normal vector DP3 normalVec.w, normalVec, normalVec; RSQ normalVec.w, normalVec.w; MUL normalVec.xyz, normalVec, normalVec.w; # normalize world space normal vector DP3 wNormalVec.w, wNormalVec, wNormalVec; RSQ wNormalVec.w, wNormalVec.w; MUL wNormalVec.xyz, wNormalVec, wNormalVec.w; # calculate vector dot products DP3_SAT NdotL.x, normalVec, lightVec; DP3_SAT NdotV.x, normalVec, viewVec; DP3 NdotV.y, wNormalVec, wViewVec; DP3_SAT NdotH.x, normalVec, halfVec; # diffuse dot product DP3_SAT light, lightVec, normalVec; #--------------------------------------------------------- # Calculate Fresnel reflectance approximation for Diffuse lighting #--------------------------------------------------------- DP3_SAT fresnelTerm.x, viewVec, normalVec; SUB fresnelTerm, 1, fresnelTerm; POW fresnelTerm, fresnelTerm.x, fresnelParms2.w; SUB_SAT R1, light, .3; MIN R1, R1, fresnelParms.zzzz; MUL rimLight, R1, fresnelTerm; # calculate directional specular term POW_SAT specular.w, NdotH.x, 64.0.x; #--------------------------------- # Convert spec. exponent to ralnge lightParms.w - lightParms.z #--------------------------------- LRP gloss.a, gloss.z, lightParms.w, lightParms.z; #--------------------------------- # Don't use specular lookup texture. Use power instead. POW specular.x, specular.x, gloss.a; POW specular.y, specular.y, gloss.a; POW specular.z, specular.z, gloss.a; #--------------------------------------------------------- MUL specular, specular, fresnelParms2.z; #--------------------------------------------------------- #--------------------------------------------------------- # Calculate & add fresnel reflectance approximation for specular #--------------------------------------------------------- MAD R3, fresnelTerm.x, fresnelParms.y, fresnelParms2.y; MUL specular, specular, R3; #--------------------------------------------------------- SLT ambient.w, ambient.w, const.x; CMP_SAT light, -ambient.w, NdotL.x, ambient; CMP specular, -ambient.w, specular.w, specular; CMP_SAT atten, -ambient.w, atten, atten.w; # combine diffuse and specular terms # ADD gloss, gloss, gloss; # modulate by the specular map MUL R3, color, .25; MUL R3, gloss, R3; MAD R3, gloss, 0.75, R3; MUL specular, specular, R3; #--------------------------------------------------------- # Calculate Self Shadow term and modulate with result. #--------------------------------------------------------- MUL_SAT gloss, lightVec.z, 4.0; MAD diffuse, rimLight, gloss, diffuse; MAD diffuse, specular, gloss, diffuse; MUL diffuse, light, diffuse; # MUL diffuse, diffuse, program.env[0]; POW diffuse.x, diffuse.x, program.env[0].x; POW diffuse.y, diffuse.y, program.env[0].x; POW diffuse.z, diffuse.z, program.env[0].x; MUL diffuse, diffuse, lightColor; MUL specular, specular, specColor; MAD color, specular, gloss, diffuse; # modulate by light & attenuation MUL color, color, light; MUL color, color, atten; POW color.x, color.x, 0.45454545454545454545454545454545.x; POW color.y, color.y, 0.45454545454545454545454545454545.x; POW color.z, color.z, 0.45454545454545454545454545454545.x; # modify by the vertex color MUL oColor.xyz, color, vColor; END