/* =========================================================================== Copyright (C) 2023-2024 Gian 'myT' Schellenbaum This file is part of Challenge Quake 3 (CNQ3). Challenge Quake 3 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 2 of the License, or (at your option) any later version. Challenge Quake 3 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 Challenge Quake 3. If not, see . =========================================================================== */ // generic shader for opaque surfaces #include "common.hlsli" #include "alpha_test.h.hlsli" #include "scene_view.h.hlsli" cbuffer RootConstants { // geometry matrix modelViewMatrix; // general uint textureIndex; uint samplerIndex; uint shaderIndexBufferIndex; uint alphaTest; uint lightTextureIndex; uint lightmapPass; float greyscale; // shader trace uint shaderTrace; // shader index: 14 - enable: 1 uint centerPixel; // y: 16 - x: 16 }; struct VIn { float3 position : POSITION; float3 normal : NORMAL; float2 texCoords : TEXCOORD0; float4 color : COLOR0; }; struct VOut { float4 position : SV_Position; float3 normal : NORMAL; float2 texCoords : TEXCOORD0; float4 color : COLOR0; float clipDist : SV_ClipDistance0; }; VOut vs(VIn input) { SceneView scene = GetSceneView(); float4 positionVS = mul(modelViewMatrix, float4(input.position.xyz, 1)); VOut output; output.position = mul(scene.projectionMatrix, positionVS); output.normal = input.normal; output.texCoords = input.texCoords; output.color = input.color; output.clipDist = dot(positionVS, scene.clipPlane); return output; } [earlydepthstencil] float4 ps(VOut input) : SV_Target { // @TODO: Voronoi tiling Texture2D texture0 = ResourceDescriptorHeap[textureIndex]; SamplerState sampler0 = ResourceDescriptorHeap[samplerIndex]; float4 dst = texture0.Sample(sampler0, input.texCoords) * input.color; if(FailsAlphaTest(dst.a, alphaTest)) { discard; } if(lightmapPass) { Texture2D lightTexture = ResourceDescriptorHeap[lightTextureIndex]; float3 directLight = lightTexture.Load(uint3(input.position.xy, 0)).rgb; dst.rgb += directLight; } dst = MakeGreyscale(dst, greyscale); // @TODO: dithering (need to figure out the tone mapping function first) if(shaderTrace & 1) { // we only store the shader index of 1 pixel uint2 fragmentCoords = uint2(input.position.xy); uint2 centerCoords = uint2(centerPixel & 0xFFFF, centerPixel >> 16); if(all(fragmentCoords == centerCoords)) { RWByteAddressBuffer shaderIndexBuffer = ResourceDescriptorHeap[shaderIndexBufferIndex]; uint shaderIndex = shaderTrace >> 1; shaderIndexBuffer.Store(0, shaderIndex); } } return dst; }