mirror of
https://bitbucket.org/CPMADevs/cnq3
synced 2025-04-17 23:12:02 +00:00
162 lines
4.7 KiB
HLSL
162 lines
4.7 KiB
HLSL
/*
|
|
===========================================================================
|
|
Copyright (C) 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 <https://www.gnu.org/licenses/>.
|
|
===========================================================================
|
|
*/
|
|
// Im3d integration
|
|
|
|
|
|
#define kAntialiasing 2.0
|
|
|
|
struct VOut
|
|
{
|
|
float4 position : SV_POSITION;
|
|
float4 color : COLOR0;
|
|
#if defined(POINTS) || defined(LINES)
|
|
float size : SIZE;
|
|
#endif
|
|
#if defined(POINTS)
|
|
float2 texCoords : UV;
|
|
#endif
|
|
#if defined(LINES)
|
|
float edgeDistance : EDGEDISTANCE;
|
|
#endif
|
|
};
|
|
|
|
|
|
#if VERTEX_SHADER
|
|
|
|
struct Vertex
|
|
{
|
|
float3 position;
|
|
float size;
|
|
uint color;
|
|
};
|
|
|
|
struct Im3dVertexShaderInput
|
|
{
|
|
matrix viewMatrix;
|
|
matrix projectionMatrix;
|
|
float2 viewport;
|
|
uint vertexOffset;
|
|
StructuredBuffer<Vertex> vertexBuffer;
|
|
uint vertexId;
|
|
};
|
|
|
|
float4 UnpackIm3dColor(uint c)
|
|
{
|
|
uint4 u = uint4((c >> 24) & 0xFFu, (c >> 16) & 0xFFu, (c >> 8) & 0xFFu, c & 0xFFu);
|
|
float4 r = float4(u) / 255.0;
|
|
|
|
return r;
|
|
}
|
|
|
|
float2 PositionFromVertexId(uint vertexId)
|
|
{
|
|
// 0 -> -1, -1
|
|
// 1 -> 1, -1
|
|
// 2 -> 1, 1
|
|
// 3 -> -1, 1
|
|
float2 result;
|
|
result.x = (2 - vertexId) <= 1 ? 1.0 : -1.0;
|
|
result.y = vertexId >= 2 ? 1.0 : -1.0;
|
|
|
|
return result;
|
|
}
|
|
|
|
VOut VertexShader(Im3dVertexShaderInput input)
|
|
{
|
|
VOut output;
|
|
|
|
#if defined(POINTS)
|
|
uint pointIndex = input.vertexOffset + (input.vertexId / 4);
|
|
Vertex vertex = input.vertexBuffer[NonUniformResourceIndex(pointIndex)];
|
|
float outSize = max(vertex.size, kAntialiasing);
|
|
float2 scale = outSize.xx / input.viewport;
|
|
float2 localPosition = PositionFromVertexId(input.vertexId % 4);
|
|
float4 position = mul(input.projectionMatrix, mul(input.viewMatrix, float4(vertex.position, 1)));
|
|
position.xy += localPosition * scale * position.w;
|
|
|
|
output.position = position;
|
|
output.color = UnpackIm3dColor(vertex.color);
|
|
output.size = outSize;
|
|
output.texCoords = localPosition * 0.5 + 0.5;
|
|
#endif
|
|
#if defined(LINES)
|
|
uint localVertexId = input.vertexId % 4;
|
|
bool lineStart = localVertexId == 0 || localVertexId == 3;
|
|
uint lineId = input.vertexId / 4;
|
|
uint vid0 = input.vertexOffset + lineId * 2; // line start, x negative (0 or 3)
|
|
uint vid1 = vid0 + 1; // line end, x positive (1 or 2)
|
|
uint vid = lineStart ? vid0 : vid1; // data for this vertex
|
|
Vertex vertex = input.vertexBuffer[NonUniformResourceIndex(vid)];
|
|
Vertex vertex0 = input.vertexBuffer[NonUniformResourceIndex(vid0)];
|
|
Vertex vertex1 = input.vertexBuffer[NonUniformResourceIndex(vid1)];
|
|
float2 localPosition = PositionFromVertexId(localVertexId);
|
|
float4 outColor = UnpackIm3dColor(vertex.color);
|
|
float outSize = vertex.size;
|
|
outColor.a *= smoothstep(0.0, 1.0, outSize / kAntialiasing);
|
|
outSize = max(outSize, kAntialiasing);
|
|
float edgeDistance = outSize * localPosition.y;
|
|
float4 pos0 = mul(input.projectionMatrix, mul(input.viewMatrix, float4(vertex0.position, 1)));
|
|
float4 pos1 = mul(input.projectionMatrix, mul(input.viewMatrix, float4(vertex1.position, 1)));
|
|
float2 dir = (pos0.xy / pos0.w) - (pos1.xy / pos1.w);
|
|
dir = normalize(float2(dir.x, dir.y * input.viewport.y / input.viewport.x)); // correct for aspect ratio
|
|
float2 tng = float2(-dir.y, dir.x) * outSize / input.viewport;
|
|
float4 position = lineStart ? pos0 : pos1;
|
|
position.xy += tng * localPosition.y * position.w;
|
|
|
|
output.position = position;
|
|
output.color = outColor;
|
|
output.size = outSize;
|
|
output.edgeDistance = edgeDistance;
|
|
#endif
|
|
#if defined(TRIANGLES)
|
|
Vertex vertex = input.vertexBuffer[NonUniformResourceIndex(input.vertexOffset + input.vertexId)];
|
|
|
|
output.position = mul(input.projectionMatrix, mul(input.viewMatrix, float4(vertex.position, 1)));
|
|
output.color = UnpackIm3dColor(vertex.color);
|
|
#endif
|
|
|
|
return output;
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
#if PIXEL_SHADER
|
|
|
|
float4 PixelShader(VOut input)
|
|
{
|
|
// we scale the color here to counter the post-process gamma/brightness
|
|
float4 result = float4(input.color.rgb * 0.5, input.color.a);
|
|
#if defined(POINTS)
|
|
float d = length(input.texCoords - float2(0.5, 0.5));
|
|
d = smoothstep(0.5, 0.5 - (kAntialiasing / input.size), d);
|
|
result.a *= d;
|
|
#endif
|
|
#if defined(LINES)
|
|
float d = abs(input.edgeDistance) / input.size;
|
|
d = smoothstep(1.0, 1.0 - (kAntialiasing / input.size), d);
|
|
result.a *= d;
|
|
#endif
|
|
|
|
return result;
|
|
}
|
|
|
|
#endif
|