From 249397bcb829cbbb7e1b324d51f0bf8f848a9923 Mon Sep 17 00:00:00 2001 From: Robert Beckebans Date: Sat, 30 Nov 2024 00:15:27 +0100 Subject: [PATCH] Added bumpyenvironment2 shader for some reflective blood experiments --- neo/renderer/Material.cpp | 9 + neo/renderer/Material.h | 10 +- neo/renderer/NVRHI/RenderBackend_NVRHI.cpp | 90 +++++++++ neo/renderer/RenderBackend.cpp | 65 ++++++- neo/renderer/RenderCommon.h | 3 + neo/renderer/RenderProgs.cpp | 20 ++ neo/renderer/RenderProgs.h | 13 ++ .../builtin/legacy/bumpyenvironment2.ps.hlsl | 124 ++++++++++++ .../builtin/legacy/bumpyenvironment2.vs.hlsl | 179 ++++++++++++++++++ neo/shaders/shaders.cfg | 2 + 10 files changed, 507 insertions(+), 8 deletions(-) create mode 100644 neo/shaders/builtin/legacy/bumpyenvironment2.ps.hlsl create mode 100644 neo/shaders/builtin/legacy/bumpyenvironment2.vs.hlsl diff --git a/neo/renderer/Material.cpp b/neo/renderer/Material.cpp index f01b20e5..7e208527 100644 --- a/neo/renderer/Material.cpp +++ b/neo/renderer/Material.cpp @@ -1918,6 +1918,10 @@ void idMaterial::ParseStage( idLexer& src, const textureRepeat_t trpDefault ) { ts->texgen = TG_REFLECT_CUBE; } + else if( !token.Icmp( "reflect2" ) ) + { + ts->texgen = TG_REFLECT_CUBE2; + } else if( !token.Icmp( "skybox" ) ) { ts->texgen = TG_SKYBOX_CUBE; @@ -2759,6 +2763,11 @@ void idMaterial::ParseMaterial( idLexer& src ) mikktspace = true; continue; } + else if( !token.Icmp( "unlit" ) ) + { + SetMaterialFlag( MF_UNLIT ); + continue; + } // lightFallofImage // specifies the image to use for the third axis of projected // light volumes diff --git a/neo/renderer/Material.h b/neo/renderer/Material.h index 53af6a96..525628c1 100644 --- a/neo/renderer/Material.h +++ b/neo/renderer/Material.h @@ -164,11 +164,12 @@ typedef enum TG_EXPLICIT, TG_DIFFUSE_CUBE, TG_REFLECT_CUBE, + TG_REFLECT_CUBE2, // RB interpolates 3 octahedrons like for ambient lighting TG_SKYBOX_CUBE, TG_WOBBLESKY_CUBE, TG_SCREEN, // screen aligned, for mirrorRenders and screen space temporaries TG_SCREEN2, - TG_GLASSWARP + TG_GLASSWARP, } texgen_t; typedef struct @@ -361,9 +362,8 @@ typedef enum MF_LOD3 = BIT( 9 ), // motorsep 11-24-2014; material flag for LOD3 iteration MF_LOD4 = BIT( 10 ), // motorsep 11-24-2014; material flag for LOD4 iteration MF_LOD_PERSISTENT = BIT( 11 ), // motorsep 11-24-2014; material flag for persistent LOD iteration - MF_GUITARGET = BIT( 12 ), // Admer: this GUI surface is used to compute a GUI render map, but a GUI should NOT be drawn on it - MF_AUTOGEN_TEMPLATE = BIT( 13 ), // Admer: this material is a template for auto-generated templates - MF_ORIGIN = BIT( 14 ), // Admer: for origin brushes + MF_ORIGIN = BIT( 12 ), // Admer: for origin brushes + MF_UNLIT = BIT( 13 ), // RB: receive no lighting } materialFlags_t; // contents flags, NOTE: make sure to keep the defines in doom_defs.script up to date with these! @@ -595,7 +595,7 @@ public: // stages, and don't interact with lights at all bool ReceivesLighting() const { - return numAmbientStages != numStages; + return ( numAmbientStages != numStages ) && ( materialFlags & MF_UNLIT ) == 0; } // returns true if the material should generate interactions on sides facing away diff --git a/neo/renderer/NVRHI/RenderBackend_NVRHI.cpp b/neo/renderer/NVRHI/RenderBackend_NVRHI.cpp index 367459ab..21c09e74 100644 --- a/neo/renderer/NVRHI/RenderBackend_NVRHI.cpp +++ b/neo/renderer/NVRHI/RenderBackend_NVRHI.cpp @@ -1787,6 +1787,96 @@ void idRenderBackend::GetCurrentBindingLayout( int type ) } } } + else if( type == BINDING_LAYOUT_OCTAHEDRON_CUBE || type == BINDING_LAYOUT_OCTAHEDRON_CUBE_SKINNED ) + { + if( type == BINDING_LAYOUT_OCTAHEDRON_CUBE_SKINNED ) + { + if( desc[0].bindings.empty() ) + { + desc[0].bindings = + { + nvrhi::BindingSetItem::ConstantBuffer( 0, paramCb, range ), + nvrhi::BindingSetItem::StructuredBuffer_SRV( 11, currentJointBuffer, nvrhi::Format::UNKNOWN, nvrhi::BufferRange( currentJointOffset, sizeof( idVec4 ) * numBoneMatrices ) ) + }; + } + else + { + auto& bindings = desc[0].bindings; + bindings[0].resourceHandle = paramCb; + bindings[0].range = range; + + bindings[1].resourceHandle = currentJointBuffer; + bindings[1].range = nvrhi::BufferRange{ currentJointOffset, sizeof( idVec4 )* numBoneMatrices }; + } + } + else + { + if( desc[0].bindings.empty() ) + { + desc[0].bindings = + { + nvrhi::BindingSetItem::ConstantBuffer( 0, paramCb, range ), + }; + } + else + { + desc[0].bindings[0].resourceHandle = paramCb; + desc[0].bindings[0].range = range; + } + } + + if( desc[1].bindings.empty() ) + { + desc[1].bindings = + { + nvrhi::BindingSetItem::Texture_SRV( 0, ( nvrhi::ITexture* )GetImageAt( 0 )->GetTextureID() ), + nvrhi::BindingSetItem::Texture_SRV( 1, ( nvrhi::ITexture* )GetImageAt( 1 )->GetTextureID() ), + nvrhi::BindingSetItem::Texture_SRV( 2, ( nvrhi::ITexture* )GetImageAt( 2 )->GetTextureID() ), + nvrhi::BindingSetItem::Texture_SRV( 3, ( nvrhi::ITexture* )GetImageAt( 3 )->GetTextureID() ) + }; + } + else + { + auto& bindings = desc[1].bindings; + bindings[0].resourceHandle = ( nvrhi::ITexture* )GetImageAt( 0 )->GetTextureID(); + bindings[1].resourceHandle = ( nvrhi::ITexture* )GetImageAt( 1 )->GetTextureID(); + bindings[1].resourceHandle = ( nvrhi::ITexture* )GetImageAt( 2 )->GetTextureID(); + bindings[1].resourceHandle = ( nvrhi::ITexture* )GetImageAt( 3 )->GetTextureID(); + } + + if( R_UsePixelatedLook() ) + { + if( desc[2].bindings.empty() ) + { + desc[2].bindings = + { + nvrhi::BindingSetItem::Sampler( 0, commonPasses.m_PointWrapSampler ), + nvrhi::BindingSetItem::Sampler( 1, commonPasses.m_LinearBorderSampler ) + }; + } + else + { + desc[2].bindings[0].resourceHandle = commonPasses.m_PointWrapSampler; + desc[2].bindings[1].resourceHandle = commonPasses.m_LinearBorderSampler; + } + } + else + { + if( desc[2].bindings.empty() ) + { + desc[2].bindings = + { + nvrhi::BindingSetItem::Sampler( 0, commonPasses.m_AnisotropicWrapSampler ), + nvrhi::BindingSetItem::Sampler( 1, commonPasses.m_LinearBorderSampler ) + }; + } + else + { + desc[2].bindings[0].resourceHandle = commonPasses.m_AnisotropicWrapSampler; + desc[2].bindings[1].resourceHandle = commonPasses.m_LinearBorderSampler; + } + } + } else if( type == BINDING_LAYOUT_BINK_VIDEO ) { if( desc[0].bindings.empty() ) diff --git a/neo/renderer/RenderBackend.cpp b/neo/renderer/RenderBackend.cpp index 225acb4a..0cc1489e 100644 --- a/neo/renderer/RenderBackend.cpp +++ b/neo/renderer/RenderBackend.cpp @@ -336,7 +336,14 @@ void idRenderBackend::BindVariableStageImage( const textureStage_t* texture, con { if( texture->image != NULL ) { - texture->image->Bind(); + if( texture->image->IsLoaded() && !texture->image->IsDefaulted() ) + { + texture->image->Bind(); + } + else + { + globalImages->defaultImage->Bind(); + } } } } @@ -356,7 +363,6 @@ void idRenderBackend::PrepareStageTexturing( const shaderStage_t* pStage, const // texgens if( pStage->texture.texgen == TG_REFLECT_CUBE ) { - // see if there is also a bump map specified const shaderStage_t* bumpStage = surf->material->GetBumpStage(); if( bumpStage != NULL ) @@ -387,7 +393,59 @@ void idRenderBackend::PrepareStageTexturing( const shaderStage_t* pStage, const renderProgManager.BindShader_Environment(); } } + } + else if( pStage->texture.texgen == TG_REFLECT_CUBE2 ) + { + idVec4 probeMins, probeMaxs, probeCenter; + probeMins[0] = viewDef->globalProbeBounds[0][0]; + probeMins[1] = viewDef->globalProbeBounds[0][1]; + probeMins[2] = viewDef->globalProbeBounds[0][2]; + probeMins[3] = viewDef->globalProbeBounds.IsCleared() ? 0.0f : 1.0f; + + probeMaxs[0] = viewDef->globalProbeBounds[1][0]; + probeMaxs[1] = viewDef->globalProbeBounds[1][1]; + probeMaxs[2] = viewDef->globalProbeBounds[1][2]; + probeMaxs[3] = 0.0f; + + idVec3 center = viewDef->globalProbeBounds.GetCenter(); + probeCenter.Set( center.x, center.y, center.z, 1.0f ); + + SetVertexParm( RENDERPARM_WOBBLESKY_X, probeMins.ToFloatPtr() ); + SetVertexParm( RENDERPARM_WOBBLESKY_Y, probeMaxs.ToFloatPtr() ); + SetVertexParm( RENDERPARM_WOBBLESKY_Z, probeCenter.ToFloatPtr() ); + + // specular cubemap blend weights + renderProgManager.SetUniformValue( RENDERPARM_LOCALLIGHTORIGIN, viewDef->radianceImageBlends.ToFloatPtr() ); + + // see if there is also a bump map specified + const shaderStage_t* bumpStage = surf->material->GetBumpStage(); + if( bumpStage != NULL ) + { + // per-pixel reflection mapping with bump mapping + GL_SelectTexture( 0 ); + bumpStage->texture.image->Bind(); + + GL_SelectTexture( 1 ); + viewDef->radianceImages[0]->Bind(); + + GL_SelectTexture( 2 ); + viewDef->radianceImages[1]->Bind(); + + GL_SelectTexture( 3 ); + viewDef->radianceImages[2]->Bind(); + + GL_SelectTexture( 0 ); + + if( surf->jointCache ) + { + renderProgManager.BindShader_BumpyEnvironment2Skinned(); + } + else + { + renderProgManager.BindShader_BumpyEnvironment2(); + } + } } else if( pStage->texture.texgen == TG_SKYBOX_CUBE ) { @@ -518,7 +576,7 @@ void idRenderBackend::FinishStageTexturing( const shaderStage_t* pStage, const d GL_SelectTexture( 0 ); } - if( pStage->texture.texgen == TG_REFLECT_CUBE ) + if( pStage->texture.texgen == TG_REFLECT_CUBE || pStage->texture.texgen == TG_REFLECT_CUBE2 ) { // see if there is also a bump map specified const shaderStage_t* bumpStage = surf->material->GetBumpStage(); @@ -531,6 +589,7 @@ void idRenderBackend::FinishStageTexturing( const shaderStage_t* pStage, const d { // per-pixel reflection mapping without bump mapping } + renderProgManager.Unbind(); } } diff --git a/neo/renderer/RenderCommon.h b/neo/renderer/RenderCommon.h index 96a74267..c3cda047 100644 --- a/neo/renderer/RenderCommon.h +++ b/neo/renderer/RenderCommon.h @@ -823,6 +823,9 @@ enum bindingLayoutType_t BINDING_LAYOUT_NORMAL_CUBE, BINDING_LAYOUT_NORMAL_CUBE_SKINNED, + BINDING_LAYOUT_OCTAHEDRON_CUBE, + BINDING_LAYOUT_OCTAHEDRON_CUBE_SKINNED, + // NO GPU SKINNING ANYMORE BINDING_LAYOUT_POST_PROCESS_INGAME, BINDING_LAYOUT_POST_PROCESS_FINAL, diff --git a/neo/renderer/RenderProgs.cpp b/neo/renderer/RenderProgs.cpp index 77494e70..f3cc5b60 100644 --- a/neo/renderer/RenderProgs.cpp +++ b/neo/renderer/RenderProgs.cpp @@ -368,6 +368,24 @@ void idRenderProgManager::Init( nvrhi::IDevice* device ) skinningLayout, normalCubeBindingLayout, samplerOneBindingLayout }; + auto octahedronCubeBindingLayoutDesc = nvrhi::BindingLayoutDesc() + .setVisibility( nvrhi::ShaderType::Pixel ) + .addItem( nvrhi::BindingLayoutItem::Texture_SRV( 0 ) ) // normal map + .addItem( nvrhi::BindingLayoutItem::Texture_SRV( 1 ) ) // radiance cube map 1 + .addItem( nvrhi::BindingLayoutItem::Texture_SRV( 2 ) ) // radiance cube map 2 + .addItem( nvrhi::BindingLayoutItem::Texture_SRV( 3 ) ); // radiance cube map 3 + + auto octahedronCubeBindingLayout = device->createBindingLayout( octahedronCubeBindingLayoutDesc ); + + bindingLayouts[BINDING_LAYOUT_OCTAHEDRON_CUBE] = + { + uniformsLayout, octahedronCubeBindingLayout, samplerTwoBindingLayout + }; + bindingLayouts[BINDING_LAYOUT_OCTAHEDRON_CUBE_SKINNED] = + { + skinningLayout, octahedronCubeBindingLayout, samplerTwoBindingLayout + }; + auto binkVideoBindingLayout = nvrhi::BindingLayoutDesc() .setVisibility( nvrhi::ShaderType::All ) .addItem( renderParmLayoutItem ) @@ -538,6 +556,8 @@ void idRenderProgManager::Init( nvrhi::IDevice* device ) { BUILTIN_ENVIRONMENT_SKINNED, "builtin/legacy/environment", "_skinned", { {"USE_GPU_SKINNING", "1" } }, true , SHADER_STAGE_DEFAULT, LAYOUT_DRAW_VERT, BINDING_LAYOUT_DEFAULT_SKINNED }, { BUILTIN_BUMPY_ENVIRONMENT, "builtin/legacy/bumpyenvironment", "", { {"USE_GPU_SKINNING", "0" } }, false, SHADER_STAGE_DEFAULT, LAYOUT_DRAW_VERT, BINDING_LAYOUT_NORMAL_CUBE }, { BUILTIN_BUMPY_ENVIRONMENT_SKINNED, "builtin/legacy/bumpyenvironment", "_skinned", { {"USE_GPU_SKINNING", "1" } }, true, SHADER_STAGE_DEFAULT, LAYOUT_DRAW_VERT, BINDING_LAYOUT_NORMAL_CUBE_SKINNED }, + { BUILTIN_BUMPY_ENVIRONMENT2, "builtin/legacy/bumpyenvironment2", "", { {"USE_GPU_SKINNING", "0" } }, false, SHADER_STAGE_DEFAULT, LAYOUT_DRAW_VERT, BINDING_LAYOUT_OCTAHEDRON_CUBE }, + { BUILTIN_BUMPY_ENVIRONMENT2_SKINNED, "builtin/legacy/bumpyenvironment2", "_skinned", { {"USE_GPU_SKINNING", "1" } }, true, SHADER_STAGE_DEFAULT, LAYOUT_DRAW_VERT, BINDING_LAYOUT_OCTAHEDRON_CUBE_SKINNED }, { BUILTIN_DEPTH, "builtin/depth", "", { {"USE_GPU_SKINNING", "0" } }, false, SHADER_STAGE_DEFAULT, LAYOUT_DRAW_VERT, BINDING_LAYOUT_CONSTANT_BUFFER_ONLY }, { BUILTIN_DEPTH_SKINNED, "builtin/depth", "_skinned", { {"USE_GPU_SKINNING", "1" } }, true, SHADER_STAGE_DEFAULT, LAYOUT_DRAW_VERT, BINDING_LAYOUT_CONSTANT_BUFFER_ONLY_SKINNED }, diff --git a/neo/renderer/RenderProgs.h b/neo/renderer/RenderProgs.h index 6abe6d9a..ce4d1e3b 100644 --- a/neo/renderer/RenderProgs.h +++ b/neo/renderer/RenderProgs.h @@ -353,10 +353,13 @@ enum BUILTIN_DEBUG_OCTAHEDRON, BUILTIN_DEBUG_OCTAHEDRON_SKINNED, // RB end + BUILTIN_ENVIRONMENT, BUILTIN_ENVIRONMENT_SKINNED, BUILTIN_BUMPY_ENVIRONMENT, BUILTIN_BUMPY_ENVIRONMENT_SKINNED, + BUILTIN_BUMPY_ENVIRONMENT2, // RB + BUILTIN_BUMPY_ENVIRONMENT2_SKINNED, // RB BUILTIN_DEPTH, BUILTIN_DEPTH_SKINNED, @@ -774,6 +777,16 @@ public: BindShader_Builtin( BUILTIN_BUMPY_ENVIRONMENT_SKINNED ); } + void BindShader_BumpyEnvironment2() + { + BindShader_Builtin( BUILTIN_BUMPY_ENVIRONMENT2 ); + } + + void BindShader_BumpyEnvironment2Skinned() + { + BindShader_Builtin( BUILTIN_BUMPY_ENVIRONMENT2_SKINNED ); + } + void BindShader_Depth() { BindShader_Builtin( BUILTIN_DEPTH ); diff --git a/neo/shaders/builtin/legacy/bumpyenvironment2.ps.hlsl b/neo/shaders/builtin/legacy/bumpyenvironment2.ps.hlsl new file mode 100644 index 00000000..ad4f8667 --- /dev/null +++ b/neo/shaders/builtin/legacy/bumpyenvironment2.ps.hlsl @@ -0,0 +1,124 @@ +/* +=========================================================================== + +Doom 3 BFG Edition GPL Source Code +Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company. +Copyright (C) 2013 Robert Beckebans + +This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code"). + +Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Doom 3 BFG Edition Source Code. If not, see . + +In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below. + +If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA. + +=========================================================================== +*/ + +#include "global_inc.hlsl" + + +// *INDENT-OFF* +Texture2D t_NormalMap : register( t0 VK_DESCRIPTOR_SET( 1 ) ); +Texture2D t_RadianceCubeMap1 : register( t1 VK_DESCRIPTOR_SET( 1 ) ); +Texture2D t_RadianceCubeMap2 : register( t2 VK_DESCRIPTOR_SET( 1 ) ); +Texture2D t_RadianceCubeMap3 : register( t3 VK_DESCRIPTOR_SET( 1 ) ); + +SamplerState s_Material : register( s0 VK_DESCRIPTOR_SET( 2 ) ); +SamplerState s_LinearClamp : register( s1 VK_DESCRIPTOR_SET( 2 ) ); + +struct PS_IN +{ + float4 position : SV_Position; + float2 texcoord0 : TEXCOORD0_centroid; + float3 texcoord1 : TEXCOORD1_centroid; + float3 texcoord2 : TEXCOORD2_centroid; + float3 texcoord3 : TEXCOORD3_centroid; + float3 texcoord4 : TEXCOORD4_centroid; + float4 color : COLOR0; +}; + +struct PS_OUT +{ + float4 color : SV_Target0; +}; +// *INDENT-ON* + + + +void main( PS_IN fragment, out PS_OUT result ) +{ + float4 bump = t_NormalMap.Sample( s_Material, fragment.texcoord0 ) * 2.0f - 1.0f; + + // RB begin + float3 localNormal; +#if defined(USE_NORMAL_FMT_RGB8) + localNormal = float3( bump.rg, 0.0f ); +#else + localNormal = float3( bump.wy, 0.0f ); +#endif + // RB end + localNormal.z = sqrt( 1.0f - dot3( localNormal, localNormal ) ); + + float3 globalNormal; + globalNormal.x = dot3( localNormal, fragment.texcoord2 ); + globalNormal.y = dot3( localNormal, fragment.texcoord3 ); + globalNormal.z = dot3( localNormal, fragment.texcoord4 ); + + float3 globalEye = normalize( fragment.texcoord1 ); + + float3 reflectionVector = globalNormal * dot3( globalEye, globalNormal ); + reflectionVector = ( reflectionVector * 2.0f ) - globalEye; + +#if 0 + // parallax box correction using portal area bounds + float hitScale = 0.0; + float3 bounds[2]; + bounds[0].x = rpWobbleSkyX.x; + bounds[0].y = rpWobbleSkyX.y; + bounds[0].z = rpWobbleSkyX.z; + + bounds[1].x = rpWobbleSkyY.x; + bounds[1].y = rpWobbleSkyY.y; + bounds[1].z = rpWobbleSkyY.z; + + // global fragment position + float3 rayStart = fragment.texcoord7.xyz; + + // we can't start inside the box so move this outside and use the reverse path + rayStart += reflectionVector * 10000.0; + + // only do a box <-> ray intersection test if we use a local cubemap + if( ( rpWobbleSkyX.w > 0.0 ) && AABBRayIntersection( bounds, rayStart, -reflectionVector, hitScale ) ) + { + float3 hitPoint = rayStart - reflectionVector * hitScale; + + // rpWobbleSkyZ is cubemap center + reflectionVector = hitPoint - rpWobbleSkyZ.xyz; + } +#endif + + //float4 envMap = t_CubeMap.Sample( samp0, reflectionVector ); + + float2 normalizedOctCoord = octEncode( reflectionVector ); + float2 normalizedOctCoordZeroOne = ( normalizedOctCoord + _float2( 1.0 ) ) * 0.5; + + const float mip = 0; + float3 radiance = t_RadianceCubeMap1.SampleLevel( s_LinearClamp, normalizedOctCoordZeroOne, mip ).rgb * rpLocalLightOrigin.x; + radiance += t_RadianceCubeMap2.SampleLevel( s_LinearClamp, normalizedOctCoordZeroOne, mip ).rgb * rpLocalLightOrigin.y; + radiance += t_RadianceCubeMap3.SampleLevel( s_LinearClamp, normalizedOctCoordZeroOne, mip ).rgb * rpLocalLightOrigin.z; + + result.color = float4( sRGBToLinearRGB( radiance.xyz ), 1.0f ) * fragment.color; +} diff --git a/neo/shaders/builtin/legacy/bumpyenvironment2.vs.hlsl b/neo/shaders/builtin/legacy/bumpyenvironment2.vs.hlsl new file mode 100644 index 00000000..f0536507 --- /dev/null +++ b/neo/shaders/builtin/legacy/bumpyenvironment2.vs.hlsl @@ -0,0 +1,179 @@ +/* +=========================================================================== + +Doom 3 BFG Edition GPL Source Code +Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company. + +This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code"). + +Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Doom 3 BFG Edition Source Code. If not, see . + +In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below. + +If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA. + +=========================================================================== +*/ + +#include "global_inc.hlsl" + +// *INDENT-OFF* +#if USE_GPU_SKINNING +StructuredBuffer matrices : register(t11); +#endif + +struct VS_IN +{ + float4 position : POSITION; + float2 texcoord : TEXCOORD0; + float4 normal : NORMAL; + float4 tangent : TANGENT; + float4 color : COLOR0; + float4 color2 : COLOR1; +}; + +struct VS_OUT +{ + float4 position : SV_Position; + float2 texcoord0 : TEXCOORD0_centroid; + float3 texcoord1 : TEXCOORD1_centroid; + float3 texcoord2 : TEXCOORD2_centroid; + float3 texcoord3 : TEXCOORD3_centroid; + float3 texcoord4 : TEXCOORD4_centroid; + float4 color : COLOR0; +}; +// *INDENT-ON* + +void main( VS_IN vertex, out VS_OUT result ) +{ +#if USE_GPU_SKINNING + float4 vNormal = vertex.normal * 2.0 - 1.0; + float4 vTangent = vertex.tangent * 2.0 - 1.0; + float3 vBinormal = cross( vNormal.xyz, vTangent.xyz ) * vTangent.w; + +//-------------------------------------------------------------- +// GPU transformation of the normal / binormal / bitangent +// +// multiplying with 255.1 give us the same result and is faster than floor( w * 255 + 0.5 ) +//-------------------------------------------------------------- + const float w0 = vertex.color2.x; + const float w1 = vertex.color2.y; + const float w2 = vertex.color2.z; + const float w3 = vertex.color2.w; + + float4 matX, matY, matZ; // must be float4 for vec4 + int joint = int( vertex.color.x * 255.1 * 3.0 ); + matX = matrices[int( joint + 0 )] * w0; + matY = matrices[int( joint + 1 )] * w0; + matZ = matrices[int( joint + 2 )] * w0; + + joint = int( vertex.color.y * 255.1 * 3.0 ); + matX += matrices[int( joint + 0 )] * w1; + matY += matrices[int( joint + 1 )] * w1; + matZ += matrices[int( joint + 2 )] * w1; + + joint = int( vertex.color.z * 255.1 * 3.0 ); + matX += matrices[int( joint + 0 )] * w2; + matY += matrices[int( joint + 1 )] * w2; + matZ += matrices[int( joint + 2 )] * w2; + + joint = int( vertex.color.w * 255.1 * 3.0 ); + matX += matrices[int( joint + 0 )] * w3; + matY += matrices[int( joint + 1 )] * w3; + matZ += matrices[int( joint + 2 )] * w3; + + float3 normal; + normal.x = dot3( matX, vNormal ); + normal.y = dot3( matY, vNormal ); + normal.z = dot3( matZ, vNormal ); + normal = normalize( normal ); + + float3 tangent; + tangent.x = dot3( matX, vTangent ); + tangent.y = dot3( matY, vTangent ); + tangent.z = dot3( matZ, vTangent ); + tangent = normalize( tangent ); + + float3 binormal; + binormal.x = dot3( matX, vBinormal ); + binormal.y = dot3( matY, vBinormal ); + binormal.z = dot3( matZ, vBinormal ); + binormal = normalize( binormal ); + + float4 modelPosition; + modelPosition.x = dot4( matX, vertex.position ); + modelPosition.y = dot4( matY, vertex.position ); + modelPosition.z = dot4( matZ, vertex.position ); + modelPosition.w = 1.0; + + result.position.x = dot4( modelPosition, rpMVPmatrixX ); + result.position.y = dot4( modelPosition, rpMVPmatrixY ); + result.position.z = dot4( modelPosition, rpMVPmatrixZ ); + result.position.w = dot4( modelPosition, rpMVPmatrixW ); + + result.texcoord0 = vertex.texcoord.xy; + + float4 toEye = rpLocalViewOrigin - modelPosition; + + result.texcoord1.x = dot3( toEye, rpModelMatrixX ); + result.texcoord1.y = dot3( toEye, rpModelMatrixY ); + result.texcoord1.z = dot3( toEye, rpModelMatrixZ ); + + result.texcoord2.x = dot3( tangent, rpModelMatrixX ); + result.texcoord3.x = dot3( tangent, rpModelMatrixY ); + result.texcoord4.x = dot3( tangent, rpModelMatrixZ ); + + result.texcoord2.y = dot3( binormal, rpModelMatrixX ); + result.texcoord3.y = dot3( binormal, rpModelMatrixY ); + result.texcoord4.y = dot3( binormal, rpModelMatrixZ ); + + result.texcoord2.z = dot3( normal, rpModelMatrixX ); + result.texcoord3.z = dot3( normal, rpModelMatrixY ); + result.texcoord4.z = dot3( normal, rpModelMatrixZ ); +#else + float4 normal = vertex.normal * 2.0 - 1.0; + float4 tangent = vertex.tangent * 2.0 - 1.0; + float3 binormal = cross( normal.xyz, tangent.xyz ) * tangent.w; + + result.position.x = dot4( vertex.position, rpMVPmatrixX ); + result.position.y = dot4( vertex.position, rpMVPmatrixY ); + result.position.z = dot4( vertex.position, rpMVPmatrixZ ); + result.position.w = dot4( vertex.position, rpMVPmatrixW ); + + result.texcoord0 = vertex.texcoord.xy; + + float4 toEye = rpLocalViewOrigin - vertex.position; + + result.texcoord1.x = dot3( toEye, rpModelMatrixX ); + result.texcoord1.y = dot3( toEye, rpModelMatrixY ); + result.texcoord1.z = dot3( toEye, rpModelMatrixZ ); + + result.texcoord2.x = dot3( tangent, rpModelMatrixX ); + result.texcoord3.x = dot3( tangent, rpModelMatrixY ); + result.texcoord4.x = dot3( tangent, rpModelMatrixZ ); + + result.texcoord2.y = dot3( binormal, rpModelMatrixX ); + result.texcoord3.y = dot3( binormal, rpModelMatrixY ); + result.texcoord4.y = dot3( binormal, rpModelMatrixZ ); + + result.texcoord2.z = dot3( normal, rpModelMatrixX ); + result.texcoord3.z = dot3( normal, rpModelMatrixY ); + result.texcoord4.z = dot3( normal, rpModelMatrixZ ); + +#endif + + result.position.xyz = psxVertexJitter( result.position ); + + result.color = rpColor; +} diff --git a/neo/shaders/shaders.cfg b/neo/shaders/shaders.cfg index 0ee96b79..f264e11f 100644 --- a/neo/shaders/shaders.cfg +++ b/neo/shaders/shaders.cfg @@ -34,6 +34,8 @@ builtin/legacy/environment.vs.hlsl -T vs -D USE_GPU_SKINNING={0,1} builtin/legacy/environment.ps.hlsl -T ps -D USE_GPU_SKINNING={0,1} builtin/legacy/bumpyenvironment.vs.hlsl -T vs -D USE_GPU_SKINNING={0,1} builtin/legacy/bumpyenvironment.ps.hlsl -T ps -D USE_GPU_SKINNING={0,1} +builtin/legacy/bumpyenvironment2.vs.hlsl -T vs -D USE_GPU_SKINNING={0,1} +builtin/legacy/bumpyenvironment2.ps.hlsl -T ps -D USE_GPU_SKINNING={0,1} builtin/legacy/skybox.vs.hlsl -T vs builtin/legacy/skybox.ps.hlsl -T ps builtin/legacy/wobblesky.vs.hlsl -T vs