/* Objectives for this shader: 1) use 3dsmax lighting (remember - the light is in view space. need to move back into world); 2) layer textures using one pass. (DONE!) 3) pan textures 4) post-process effects of bloom - this means we need to gamma correct our output, then blur the shit out of it. 5) normal map modulation; (DONE!) */ float4x4 worldViewProj : WorldViewProjection; float4x4 worldX : World; float4x4 worldITX : WorldInverseTranspose; float4x4 viewX : View; float4x3 viewIX : ViewInverse; float wTime : TIME; bool useNormalMap = true; float bumpScale = 1.0f; // 3dsmax camera position semantic //float3 cameraPos : WORLDCAMERAPOSITION; // 3dsmax texcoord definitions. int texcoord0 : Texcoord < int Texcoord = 0; int MapChannel = 1; string UIWidget = "None"; >; int texcoord1 : Texcoord < int Texcoord = 1; int MapChannel = 0; string UIWidget = "None"; >; struct appData { float4 position : POSITION; float4 color : COLOR0; float3 normal : NORMAL; float3 binormal : BINORMAL; float3 tangent : TANGENT; float4 vColor : TEXCOORD1; float2 UV0 : TEXCOORD0; }; struct vertexOutput { float4 position : POSITION; float4 color : COLOR0; float4 vColor : TEXCOORD1; float2 UV0 : TEXCOORD0; float3 wPos : TEXCOORD3; float3 binormal : TEXCOORD4; float3 normal : TEXCOORD5; float3 tangent : TEXCOORD6; float3 eyeDir : TEXCOORD7; }; struct simple_vertexOutput { float4 position : POSITION; float4 color : COLOR0; }; ///////////// // light structs ///////////// struct pointLight_data { float3 d_color; float d_intensity; float3 position; float3 s_intensity; }; struct directionLight_data { float3 d_color; float d_intensity; float3 direction; float3 s_intensity; }; struct rimLight_data { float3 d_color; float d_intensity; float range; }; ///////////// // Textures & Options // organized to show up in a logical order within 3dsmax. // // for this material we want - // magma tex // rock tex (over magma) // 2 panning normal maps for magma. // normal map for rock tex. // specular map for rocks (does this make sense?) ///////////// bool useLight1 < string UIName="Use Light 1";> = false; float3 lightPosition : POSITION < string UIName = "Light 1"; string Object = "Omni01"; string Space = "World"; int RefID = 0; > = {0,40,0}; float4 lightColor1 : LightColor < int LightRef = 0; > = float4(1.0f, 1.0f, 1.0f, 1.0f); bool useLight2 < string UIName="Use Light 2";> = false; float3 lightPosition2 : POSITION < string UIName = "Light 2"; string Object = "Omni02"; string Space = "World"; int RefID = 1; > = {0,40,0}; float4 lightColor2 : LightColor < int LightRef = 1; > = float4(1.0f, 1.0f, 1.0f, 1.0f); float3 ambientColor = (1,1,1); float lavaAmount < string UIName = "Igneous Fade"; float UIMin = 0.0f; float UIMax = 1.0f; float UIStep = 0.01f; string UIWidget = "slider"; >; // lava rock textures /* bool useUVDebug < string UIName = "use uv debug";> = false; texture UVDebug < string UIName = "Uv Debug"; >; */ texture IgneousRockTex < string UIName = "Igneous Diffuse"; >; texture IgneousRockNormal < string UIName = "Igneous Normal"; >; bool useRockNormalStr = true; float RockNormalStrength < string UIName = " Normal Strength"; > = 1.0; bool swapRG = false; bool flipR = false; bool flipG = false; bool useSpecularMap < string UIName = "Use Igneous Spec Map"; >; texture IgneousRockSpecular < string UIName = " Igneous Spec"; >; float specularPower < string UIName = " Igneous Specular Power"; float UIMin = 0.0f; float UIMax = 100.0f; float UIStep = 1.0f; string UIWidget = "slider"; > = 32.0; float specularIntensity < string UIName = " Igneous Specular Intensity"; float UIMin = -0.0f; float UIMax = 5.0f; float UIStep = 0.1f; string UIWidget = "slider"; > = 1.0; // magma textures float magmaIllumination < string UIName = "Magma Illumination"; float UIMin = 0.0f; float UIMax = 10.0f; float UIStep = 0.1f; string UIWidget = "slider"; >; texture magmaTex < string UIName = "Magma Diffuse"; >; float magSpecularPower < string UIName = " Magma Specular Power"; float UIMin = 0.0f; float UIMax = 100.0f; float UIStep = 1.0f; string UIWidget = "slider"; > = 32.0; float magSpecularIntensity < string UIName = " Magma Specular Intensity"; float UIMin = -0.0f; float UIMax = 5.0f; float UIStep = 0.1f; string UIWidget = "slider"; > = 1.0; texture magmaNormalMap_surface < string UIName = "Magma Normal"; >; float normalStrength_surface < string UIName = " Normal Strength"; float UIMin = 0.0f; float UIMax = 5.0f; float UIStep = 0.01f; string UIWidget = "slider"; > = 1.0; bool mag_swapRG = false; bool mag_flipR = false; bool mag_flipG = false; texture magmaNormalMap_panning < string UIName = "Panning Normal"; >; float normalStrength_panning < string UIName = " Normal Strength"; float UIMin = 0.0f; float UIMax = 5.0f; float UIStep = 0.01f; string UIWidget = "slider"; > = 1.0; bool pan_swapRG = false; bool pan_flipR = false; bool pan_flipG = false; ///////////// // Samplers ///////////// // samplers for the rock-related textures; sampler s_IgneousRockTex = sampler_state { texture = ; AddressU = Wrap; AddressV = Wrap; }; sampler s_IgneousRockNormal = sampler_state { texture = ; AddressU = Wrap; AddressV = Wrap; }; sampler s_IgneousRockSpecular = sampler_state { texture = ; AddressU = Wrap; AddressV = Wrap; }; // samplers for the magma-related textures; sampler s_magmaTex = sampler_state { texture = ; AddressU = Wrap; AddressV = Wrap; }; sampler s_MagmaNormalMap_surface = sampler_state { texture = ; AddressU = Wrap; AddressV = Wrap; }; sampler s_MagmaNormalMap_panning = sampler_state { texture = ; AddressU = Wrap; AddressV = Wrap; }; ///////////// // Light methods ///////////// float3 pointLight(pointLight_data lightData, float3 worldpos, float3 normal, float3 color, float3 eyeDir, float specIntensity, float specPower) { float3 lightDir = lightData.position - worldpos; lightDir = normalize(lightDir); float a = saturate(dot(lightDir, normal)); float3 diffuseColor = a * (lightData.d_color * lightData.d_intensity) * color; //float3 diffuseColor = color * a; // now do specular float3 halfVec = normalize(lightDir + eyeDir); float3 specularColor = pow(saturate(dot(halfVec, normal)), specPower); specularColor *= specIntensity; //outputColor = diffuseColor + specularColor; return (diffuseColor + specularColor); } float3 directionLight(directionLight_data lightData, float3 normal, float3 color, float3 eyeDir, float specPower) { float3 outputColor = float3(0,0,0); float a = saturate(dot(normalize(lightData.direction), normal)); float3 halfVec = normalize(lightData.direction + eyeDir); float3 diffuseColor = color * (lightData.d_color * lightData.d_intensity) * a; float3 specularColor = pow(dot(halfVec, normal), specularPower) * specularIntensity * specPower; outputColor = diffuseColor + specularColor; return outputColor; } ///////////// // Vertex shaders ///////////// vertexOutput vert_shader( appData in_appData ) { vertexOutput vert_out; vert_out.position = mul(in_appData.position, worldViewProj); vert_out.color = float4(0,0,0,1); // iqnitialize - cant set just rgb without initialization, it seems. vert_out.color.rgb = ambientColor; // set, because ambientColor = float3 while vert_out.color = float4 vert_out.UV0 = in_appData.UV0; //vert_out.UV1 = in_appData.UV1; vert_out.wPos = mul(in_appData.position, worldX); vert_out.normal = in_appData.normal; vert_out.tangent = in_appData.tangent; vert_out.binormal = in_appData.binormal; vert_out.eyeDir = normalize(viewIX[3].xyz - vert_out.wPos);; vert_out.vColor = in_appData.vColor; return vert_out; } ///////////// // Pixel Shaders ///////////// //////// // single pass magma layer //////// float4 ps_magmaLayer(vertexOutput vert_in) : COLOR { float4 output_color = vert_in.color; float3x3 tanToWorldSpace; tanToWorldSpace[0].xyz = normalize(mul(vert_in.binormal, (float3x3)worldX)); tanToWorldSpace[1].xyz = normalize(mul(-vert_in.tangent, (float3x3)worldX)); tanToWorldSpace[2].xyz = normalize(mul(vert_in.normal, (float3x3)worldX)); // build the texture of our normal maps float3 curNormal; if (useNormalMap) { // build the texture of our normal maps; curNormal = tex2D(s_MagmaNormalMap_surface, vert_in.UV0); curNormal += tex2D(s_MagmaNormalMap_panning, vert_in.UV0 * 1.2 + (wTime/ 100)); curNormal /= 2.0; // distort our UVs vert_in.UV0 += curNormal.xz * 0.3; // now resample the normal map with distorted UVs to get a normal from the new location; curNormal = tex2D(s_MagmaNormalMap_surface, vert_in.UV0); if (mag_swapRG) curNormal.rg = (curNormal.g, curNormal.r); if (mag_flipR) curNormal.r = 1 - curNormal.r; if (mag_flipG) curNormal.g = 1 - curNormal.g; float3 panningNormal = tex2D(s_MagmaNormalMap_panning, vert_in.UV0 * 1.2 + (wTime/ 100)); if (pan_swapRG) panningNormal.rg = (panningNormal.g, panningNormal.r); if (pan_flipR) panningNormal.r = 1 - panningNormal.r; if (pan_flipG) panningNormal.g = 1 - panningNormal.g; curNormal += panningNormal; curNormal /= 2.0f; curNormal = mul(curNormal * 2 - 1, tanToWorldSpace); } else { // else, just use the default normal value curNormal = mul(float3(0.5, 0.5, 1.0) * 2 - 1, tanToWorldSpace); } // build our light data structs. pointLight_data pl1; pl1.d_color = lightColor1.rgb; pl1.d_intensity = lightColor1.a; pl1.position = lightPosition; pl1.s_intensity = lightColor1.a; pointLight_data pl2; pl2.d_color = lightColor2.rgb; pl2.d_intensity = lightColor2.a; pl2.position = lightPosition2; pl2.s_intensity = lightColor2.a; // magma texture, plus base illumination. output_color.rgb = tex2D(s_magmaTex, vert_in.UV0); output_color.rgb += output_color.rgb * magmaIllumination; // light with both of our lights. if (useLight1) output_color.rgb = pointLight(pl1, vert_in.wPos, curNormal, output_color.rgb, vert_in.eyeDir, (magSpecularIntensity * pl1.s_intensity), magSpecularPower); if (useLight2) output_color.rgb += pointLight(pl2, vert_in.wPos, curNormal, output_color.rgb, vert_in.eyeDir, (magSpecularIntensity * pl1.s_intensity), magSpecularPower); output_color.a = 1; return output_color; } // single pass igneous rock layer only. float4 ps_igneousLayer(vertexOutput vert_in) : COLOR { float4 output_color = vert_in.color; float3 curNormal; float3x3 tanToWorldSpace; tanToWorldSpace[0].xyz = normalize(mul(vert_in.binormal, (float3x3)worldX)); tanToWorldSpace[1].xyz = normalize(mul(-vert_in.tangent, (float3x3)worldX)); tanToWorldSpace[2].xyz = normalize(mul(vert_in.normal, (float3x3)worldX)); float4 rockDiffuse = tex2D(s_IgneousRockTex, vert_in.UV0); int lerpValue = (1 - lavaAmount + rockDiffuse.a + vert_in.vColor.r); // make our 1 -> 0 and our 0 -> 1 lerpValue = !lerpValue; output_color.rgb = rockDiffuse; output_color.a = lerpValue; if (useNormalMap) { float3 normalTex = tex2D(s_IgneousRockNormal, vert_in.UV0); if (swapRG) normalTex.rg = float2(normalTex.g, normalTex.r); if (flipR) normalTex.r = 1 - normalTex.r; if (flipG) normalTex.g = 1 - normalTex.g; curNormal = mul(normalTex * 2 - 1, tanToWorldSpace); if (useRockNormalStr) curNormal.z *= RockNormalStrength; else curNormal *= RockNormalStrength; } else { curNormal = mul(float3(0.5, 0.5, 1.0) * 2 - 1, tanToWorldSpace); } pointLight_data pl1; pl1.d_color = lightColor1.rgb; pl1.d_intensity = lightColor1.a; pl1.position = lightPosition; pl1.s_intensity = lightColor1.a; pointLight_data pl2; pl2.d_color = lightColor2.rgb; pl2.d_intensity = lightColor2.a; pl2.position = lightPosition2; pl2.s_intensity = lightColor2.a; float3 specTex; if (useSpecularMap) specTex = tex2D(s_IgneousRockSpecular, vert_in.UV0) * specularIntensity; else specTex = (1,1,1) * specularIntensity; // light our surface\ if (useLight1) { output_color.rgb = pointLight(pl1, vert_in.wPos, curNormal, rockDiffuse, vert_in.eyeDir, (specTex * specularIntensity), specularPower); } if (useLight2) { output_color.rgb += pointLight(pl2, vert_in.wPos, curNormal, rockDiffuse, vert_in.eyeDir, (specTex * specularIntensity), specularPower); } return output_color; } ///////////// // techniques ///////////// /* technique lavaShader { pass p0 { CullMode = None; VertexShader = compile vs_3_0 vert_shader(); PixelShader = compile ps_3_0 ps_singlePass(); } } */ technique lavashader_2pass { pass magmaPass { CullMode = None; VertexShader = compile vs_3_0 vert_shader(); PixelShader = compile ps_3_0 ps_magmaLayer(); } pass igneousPass { CullMode = None; VertexShader = compile vs_3_0 vert_shader(); PixelShader = compile ps_3_0 ps_igneousLayer(); } }