// This code contains NVIDIA Confidential Information and is disclosed // under the Mutual Non-Disclosure Agreement. // // Notice // ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES // NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO // THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT, // MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. // // NVIDIA Corporation assumes no responsibility for the consequences of use of such // information or for any infringement of patents or other rights of third parties that may // result from its use. No license is granted by implication or otherwise under any patent // or patent rights of NVIDIA Corporation. No third party distribution is allowed unless // expressly authorized by NVIDIA. Details are subject to change without notice. // This code supersedes and replaces all information previously supplied. // NVIDIA Corporation products are not authorized for use as critical // components in life support devices or systems without express written approval of // NVIDIA Corporation. // // Copyright © 2008- 2013 NVIDIA Corporation. All rights reserved. // // NVIDIA Corporation and its licensors retain all intellectual property and proprietary // rights in and to this software and related documentation and any modifications thereto. // Any use, reproduction, disclosure or distribution of this software and related // documentation without an express license agreement from NVIDIA Corporation is // strictly prohibited. // #define GFSDK_WAVEWORKS_SM3 #define GFSDK_WAVEWORKS_DECLARE_GEOM_VS_CONSTANT(Type,Label,Regoff) Type Label; #include "GFSDK_WaveWorks_Quadtree.fxh" #define GFSDK_WAVEWORKS_DECLARE_ATTR_VS_CONSTANT(Type,Label,Regoff) Type Label; #define GFSDK_WAVEWORKS_DECLARE_ATTR_VS_SAMPLER(Label,TextureLabel,Regoff) sampler Label; #define GFSDK_WAVEWORKS_DECLARE_ATTR_PS_CONSTANT(Type,Label,Regoff) Type Label; #define GFSDK_WAVEWORKS_DECLARE_ATTR_PS_SAMPLER(Label,TextureLabel,Regoff) sampler Label; #include "GFSDK_WaveWorks_Attributes.fxh" //------------------------------------------------------------------------------------ // Global variables //------------------------------------------------------------------------------------ // Constant // Constant float4x4 g_matViewProj; float3 g_SkyColor; float3 g_DeepColor; float3 g_BendParam = {0.1f, -0.4f, 0.2f}; float3 g_SunDir = {0.936016f, -0.343206f, 0.0780013f}; float3 g_SunColor = {1.0f, 1.0f, 0.6f}; float g_Shineness = 20.0f; float3 g_WaterDeepColor={0.0,0.4,0.6}; float3 g_WaterScatterColor={0.0,0.7,0.6}; float3 g_WaterSpecularColor={1,0.8,0.5}; float2 g_WaterColorIntensity={0.2,0.1}; float g_WaterSpecularIntensity = 0.7f; float3 g_FoamColor = {0.90f, 0.95f, 1.0f}; float3 foam_underwater_color = {0.90f, 0.95f, 1.0f}; //----------------------------------------------------------------------------------- // Texture & Samplers //----------------------------------------------------------------------------------- texture1D g_texColorMap; textureCUBE g_texCubeMap; texture2D g_texFoamIntensityMap; texture2D g_texFoamDiffuseMap; // Blending map for ocean color sampler g_samplerColorMap = sampler_state { texture = (g_texColorMap); MipFilter = None; MinFilter = Linear; MagFilter = Linear; AddressU = Clamp; }; // Environment map sampler g_samplerCubeMap = sampler_state { texture = (g_texCubeMap); MipFilter = Linear; MinFilter = Linear; MagFilter = Linear; AddressU = Clamp; AddressV = Clamp; AddressW = Clamp; }; // Foam diffuse map (bubbles) sampler g_samplerFoamDiffuseMap = sampler_state { texture = (g_texFoamDiffuseMap); MipFilter = Linear; MinFilter = Linear; MagFilter = Linear; AddressU = Wrap; AddressV = Wrap; AddressW = Wrap; }; // Foam intensity map (Perlin-like) sampler g_samplerFoamIntensityMap = sampler_state { texture = (g_texFoamIntensityMap); MipFilter = Linear; MinFilter = Linear; MagFilter = Linear; AddressU = Wrap; AddressV = Wrap; AddressW = Wrap; }; struct VS_OUTPUT { float4 pos_clip : SV_Position; GFSDK_WAVEWORKS_INTERPOLATED_VERTEX_OUTPUT NV_ocean_interp; float3 world_displacement: TEXCOORD4; float3 world_pos_undisplaced: TEXCOORD5; }; //----------------------------------------------------------------------------- // Name: OceanWaveVS // Type: Vertex shader // Desc: //----------------------------------------------------------------------------- VS_OUTPUT OceanWaveVS(GFSDK_WAVEWORKS_VERTEX_INPUT In) { GFSDK_WAVEWORKS_VERTEX_OUTPUT NV_ocean = GFSDK_WaveWorks_GetDisplacedVertex(In); VS_OUTPUT Output; Output.NV_ocean_interp = NV_ocean.interp; Output.pos_clip = mul(float4(NV_ocean.pos_world,1), g_matViewProj); Output.world_displacement = NV_ocean.world_displacement; Output.world_pos_undisplaced = NV_ocean.pos_world - NV_ocean.world_displacement; return Output; } //----------------------------------------------------------------------------- // Name: OceanWavePS // Type: Pixel shader // Desc: //----------------------------------------------------------------------------- float4 OceanWavePS(VS_OUTPUT In) : COLOR { GFSDK_WAVEWORKS_SURFACE_ATTRIBUTES surface_attributes = GFSDK_WaveWorks_GetSurfaceAttributes(In.NV_ocean_interp); float fresnel_factor; float diffuse_factor; float specular_factor; float scatter_factor; float3 pixel_to_light_vector=g_SunDir; float3 pixel_to_eye_vector=surface_attributes.eye_dir; float3 reflected_eye_to_pixel_vector = reflect(-surface_attributes.eye_dir, surface_attributes.normal); float cos_angle = dot(surface_attributes.normal, surface_attributes.eye_dir); // ramp.x for fresnel term. ramp.y for atmosphere blending float3 ramp = tex1D(g_samplerColorMap, cos_angle).xyz; // A worksaround to deal with "indirect reflection vectors" (which are rays requiring multiple // reflections to reach the sky). if (reflected_eye_to_pixel_vector.z < g_BendParam.x) ramp = lerp(ramp, g_BendParam.z, (g_BendParam.x - reflected_eye_to_pixel_vector.z)/(g_BendParam.x - g_BendParam.y)); reflected_eye_to_pixel_vector.z = max(0, reflected_eye_to_pixel_vector.z); // simulating scattering/double refraction: light hits the side of wave, travels some distance in water, and leaves wave on the other side // it's difficult to do it physically correct without photon mapping/ray tracing, so using simple but plausible emulation below // only the crests of water waves generate double refracted light scatter_factor=0.01*max(0,In.world_displacement.z*0.001+0.3); // the waves that lie between camera and light projection on water plane generate maximal amount of double refracted light scatter_factor*=pow(max(0.0,dot(normalize(float3(pixel_to_light_vector.x,0.0,pixel_to_light_vector.z)),-pixel_to_eye_vector)),2.0); // the slopes of waves that are oriented back to light generate maximal amount of double refracted light scatter_factor*=pow(max(0.0,0.5-0.5*dot(pixel_to_light_vector,surface_attributes.normal)),3.0); // water crests gather more light than lobes, so more light is scattered under the crests scatter_factor+=2.0*g_WaterColorIntensity.y*max(0,In.world_displacement.z*0.001+0.3)* // the scattered light is best seen if observing direction is normal to slope surface max(0,dot(pixel_to_eye_vector,surface_attributes.normal)); // calculating fresnel factor //float r=(1.2-1.0)/(1.2+1.0); //fresnel_factor = max(0.0,min(1.0,r+(1.0-r)*pow(1.0-dot(surface_attributes.normal,pixel_to_eye_vector),2.0))); //float r=(1.0 - 1.13)*(1.0 - 1.13)/(1.0 + 1.13); //fresnel_factor = r + (1.0-r)*pow(saturate(1.0 - dot(surface_attributes.normal,pixel_to_eye_vector)),4.0); fresnel_factor=ramp.x; // calculating diffuse intensity of water surface itself diffuse_factor=g_WaterColorIntensity.x+g_WaterColorIntensity.y*max(0,dot(pixel_to_light_vector,surface_attributes.normal)); float3 refraction_color=diffuse_factor*g_WaterDeepColor; // adding color that provide foam bubbles spread in water refraction_color += foam_underwater_color*saturate(surface_attributes.foam_turbulent_energy*0.2); // adding scatter light component refraction_color+=g_WaterScatterColor*scatter_factor; // reflection color float3 reflection_color = lerp(g_SkyColor,texCUBE(g_samplerCubeMap, reflected_eye_to_pixel_vector).xyz, ramp.y); // applying Fresnel law float3 water_color = lerp(refraction_color,reflection_color,fresnel_factor); // applying surface foam provided by turbulent energy // low frequency foam map float foam_intensity_map_lf = 1.0*tex2D(g_samplerFoamIntensityMap, In.world_pos_undisplaced.xy*0.04*float2(1,1)).x - 1.0; // high frequency foam map float foam_intensity_map_hf = 1.0*tex2D(g_samplerFoamIntensityMap, In.world_pos_undisplaced.xy*0.15*float2(1,1)).x - 1.0; // ultra high frequency foam map float foam_intensity_map_uhf = 1.0*tex2D(g_samplerFoamIntensityMap, In.world_pos_undisplaced.xy*0.3*float2(1,1)).x; float foam_intensity; foam_intensity = saturate(foam_intensity_map_hf + min(3.5,1.0*surface_attributes.foam_turbulent_energy-0.2)); foam_intensity += (foam_intensity_map_lf + min(1.5,1.0*surface_attributes.foam_turbulent_energy)); foam_intensity -= 0.1*saturate(-surface_attributes.foam_surface_folding); foam_intensity = max(0,foam_intensity); foam_intensity *= 1.0+0.8*saturate(surface_attributes.foam_surface_folding); float foam_bubbles = tex2D(g_samplerFoamDiffuseMap, In.world_pos_undisplaced.xy).r; foam_bubbles = saturate(5.0*(foam_bubbles-0.8)); // applying foam hats foam_intensity += max(0,foam_intensity_map_uhf*2.0*surface_attributes.foam_wave_hats); foam_intensity = pow(foam_intensity, 0.7); foam_intensity = saturate(foam_intensity*foam_bubbles*1.0); // // foam diffuse color float foam_diffuse_factor=max(0,0.8+max(0,0.2*dot(pixel_to_light_vector,surface_attributes.normal))); water_color = lerp(water_color,foam_diffuse_factor*float3(1.0,1.0,1.0),foam_intensity); // calculating specular factor reflected_eye_to_pixel_vector=-pixel_to_eye_vector+2.0*dot(pixel_to_eye_vector,surface_attributes.normal)*surface_attributes.normal; specular_factor=pow(max(0,dot(pixel_to_light_vector,reflected_eye_to_pixel_vector)),g_Shineness); // adding specular component //water_color+=g_WaterSpecularIntensity*specular_factor*g_WaterSpecularColor*/*fresnel_factor*/saturate(1.0-5.0*foam_intensity); return float4(water_color, 1); } float4 g_PatchColor; float4 OceanWireframePS(VS_OUTPUT In) : COLOR { return g_PatchColor; } //----------------------------------------------------------------------------- // Name: OceanWaveTech // Type: Technique // Desc: //----------------------------------------------------------------------------- technique RenderOceanSurfTech { pass Pass_PatchVS_WavePS { VertexShader = compile vs_3_0 OceanWaveVS(); PixelShader = compile ps_3_0 OceanWavePS(); ZEnable = True; ZFunc = LessEqual; ZWriteEnable = True; FillMode = Solid; CullMode = CW; AlphaBlendEnable = False; AlphaTestEnable = False; ColorWriteEnable = 0x0f; StencilEnable = False; } // Wireframe pass Pass_PatchWireframe { VertexShader = compile vs_3_0 OceanWaveVS(); PixelShader = compile ps_3_0 OceanWireframePS(); ZEnable = True; AlphaBlendEnable = False; ZFunc = LessEqual; ZWriteEnable = True; FillMode = Wireframe; CullMode = None; AlphaTestEnable = False; ColorWriteEnable = 0x0f; StencilEnable = False; } } // Buffer selector int g_BufferType; //----------------------------------------------------------------------------- // Following only for debug //----------------------------------------------------------------------------- struct VS_DEBUG_OUTPUT { float4 pos_clip : POSITION; float2 tex_coord : TEXCOORD1; }; //----------------------------------------------------------------------------- // Name: DebugTextureVS // Type: Vertex shader //----------------------------------------------------------------------------- VS_DEBUG_OUTPUT DisplayBufferVS(float4 vPos : POSITION, float2 vTexCoord : TEXCOORD0) { VS_DEBUG_OUTPUT Output; Output.pos_clip = vPos; Output.tex_coord = vTexCoord; return Output; } //----------------------------------------------------------------------------- // Name: DisplayBufferPS // Type: Pixel shader //----------------------------------------------------------------------------- float4 DisplayBufferPS(VS_DEBUG_OUTPUT In) : COLOR { // FXC in Mar09 DXSDK can't compile the following code correctly. //if (g_BufferType == 1) // return tex2Dlod(g_samplerHeightMap, float4(In.tex_coord, 0, 0)) * 0.005f + 0.5f; //else if (g_BufferType == 2) //{ // float2 grad = tex2Dlod(g_samplerGradientMap, float4(In.tex_coord, 0, 0)).xy; // float3 normal = float3(grad, g_TexelLength_x2); // return float4(normalize(normal) * 0.5f + 0.5f, 0); //} //else if (g_BufferType == 3) //{ // float fold = tex2D(g_samplerGradientMap, In.tex_coord).w; // return fold * 0.5f; //} //else // return 0; //float4 height = tex2Dlod(g_samplerHeightMap, float4(In.tex_coord, 0, 0)) * 0.005f + 0.5f; //float4 grad = tex2Dlod(g_samplerGradientMap, float4(In.tex_coord, 0, 0)); //float4 normal = float4(normalize(float3(grad.xy, g_TexelLength_x2)) * 0.5f + 0.5f, 0); //float4 fold = grad.w * 0.5f; //float4 color = (g_BufferType < 2) ? height : ((g_BufferType < 3) ? normal : fold); //return color; return tex2D(g_samplerColorMap, In.tex_coord); } //----------------------------------------------------------------------------- // Name: DisplayBufferTech // Type: Technique // Desc: For debug and performance tuning purpose: outputs a floating-point // on screen. //----------------------------------------------------------------------------- technique DisplayBufferTech { pass P0 { VertexShader = compile vs_3_0 DisplayBufferVS(); PixelShader = compile ps_3_0 DisplayBufferPS(); AlphaBlendEnable = True; SrcBlend = SrcAlpha; DestBlend = InvSrcAlpha; ZEnable = True; ZWriteEnable = True; ZFunc = Always; FillMode = Solid; CullMode = None; StencilEnable = False; AlphaTestEnable = False; ColorWriteEnable = 0x0f; } }