tr1/output: rewrite room drawing

This commit is contained in:
Marcin Kurczewski 2025-03-31 19:24:47 +02:00
parent 01e18f2cf0
commit 273a63bafe
26 changed files with 992 additions and 418 deletions

View file

@ -1,15 +1,22 @@
#define WALL_L 1024
#define NEUTRAL_SHADE 0x1000
#define MAX_SHADE 0x1FFF
#define VERT_NO_CAUSTICS 0x01
#define WIBBLE_SIZE 32
#define MAX_WIBBLE 2
#define PI 3.1415926538
vec3 waterWibble(vec4 position, vec2 viewportSize, float wibbleOffset)
vec3 waterWibble(vec4 position, vec2 viewportSize, int time)
{
// get screen coordinates
vec3 ndc = position.xyz / position.w; //perspective divide/normalize
vec2 viewportCoord = ndc.xy * 0.5 + 0.5; //ndc is -1 to 1 in GL. scale for 0 to 1
vec2 viewportPixelCoord = viewportCoord * viewportSize;
float amplitude = 2.0;
viewportPixelCoord.x += sin((wibbleOffset + viewportPixelCoord.y) * 2.0 * PI / 32) * amplitude;
viewportPixelCoord.y += sin((wibbleOffset + viewportPixelCoord.x) * 2.0 * PI / 32) * amplitude;
viewportPixelCoord.x += sin((float(time) + viewportPixelCoord.y) * 2.0 * PI / WIBBLE_SIZE) * MAX_WIBBLE;
viewportPixelCoord.y += sin((float(time) + viewportPixelCoord.x) * 2.0 * PI / WIBBLE_SIZE) * MAX_WIBBLE;
// reverse transform
viewportCoord = viewportPixelCoord / viewportSize;
@ -17,6 +24,24 @@ vec3 waterWibble(vec4 position, vec2 viewportSize, float wibbleOffset)
return ndc * position.w;
}
float shadeFog(float shade, float depth, vec2 fog)
{
float fogBegin = fog.x;
float fogEnd = fog.y;
if (depth < fogBegin) {
return shade + 0.0;
} else if (depth >= fogEnd) {
return shade + float(MAX_SHADE);
} else {
return shade + (depth - fogBegin) * MAX_SHADE / (fogEnd - fogBegin);
}
}
vec3 applyShade(vec3 color, float shade)
{
return color * (2.0 - (shade / NEUTRAL_SHADE));
}
bool discardTranslucent(sampler2D tex, vec2 uv)
{
// do not use smoothing for chroma key

View file

@ -0,0 +1,91 @@
#ifdef VERTEX
uniform int uTime;
uniform samplerBuffer uUVW; // texture u, v, layer
uniform vec2 uViewportSize;
uniform mat4 uMatProjection;
uniform mat4 uMatModelView;
uniform bool uTrapezoidFilterEnabled;
uniform bool uWibbleEffect;
layout(location = 0) in vec3 inPosition;
layout(location = 1) in int inUVWIdx;
layout(location = 2) in vec2 inTrapezoidRatios;
layout(location = 3) in int inFlags;
layout(location = 4) in float inShade;
out vec4 gWorldPos;
flat out int gFlags;
flat out int gTexLayer;
out vec2 gTexUV;
out vec2 gTrapezoidRatios;
out float gShade;
void main(void) {
gWorldPos = uMatModelView * vec4(inPosition.xyz, 1.0);
gl_Position = uMatProjection * gWorldPos;
if (uWibbleEffect && (inFlags & VERT_NO_CAUSTICS) == 0) {
gl_Position.xyz =
waterWibble(gl_Position, uViewportSize, uTime);
}
vec3 uvw = texelFetch(uUVW, int(inUVWIdx)).xyz;
gFlags = inFlags;
gTexLayer = int(uvw.z);
gTexUV = uvw.xy;
gTrapezoidRatios = inTrapezoidRatios;
if (uTrapezoidFilterEnabled) {
gTexUV *= inTrapezoidRatios;
}
gShade = inShade;
}
#elif defined(FRAGMENT)
uniform int uTime;
uniform sampler2DArray uTexAtlas;
uniform bool uSmoothingEnabled;
uniform bool uAlphaDiscardEnabled;
uniform bool uTrapezoidFilterEnabled;
uniform float uAlphaThreshold;
uniform float uBrightnessMultiplier;
uniform vec3 uGlobalTint;
uniform vec2 uFog; // x = fog start, y = fog end
uniform bool uWaterEffect;
in vec4 gWorldPos;
flat in int gFlags;
flat in int gTexLayer;
in vec2 gTexUV;
in vec2 gTrapezoidRatios;
in float gShade;
out vec4 outColor;
void main(void) {
vec4 texColor = vec4(1);
vec3 texCoords = vec3(gTexUV.x, gTexUV.y, gTexLayer);
if (uTrapezoidFilterEnabled) {
texCoords.xy /= gTrapezoidRatios.xy;
}
if (texCoords.z >= 0) {
if (uAlphaDiscardEnabled && uSmoothingEnabled && discardTranslucent(uTexAtlas, texCoords)) {
discard;
}
texColor = texture(uTexAtlas, texCoords);
if (uAlphaThreshold >= 0.0 && texColor.a <= uAlphaThreshold) {
discard;
}
}
float shade = gShade;
shade = shadeFog(shade, gWorldPos.z, uFog);
texColor.rgb = applyShade(texColor.rgb, shade);
texColor.rgb *= uBrightnessMultiplier;
texColor.rgb *= uGlobalTint;
outColor = vec4(texColor.rgb, 1.0);
}
#endif

View file

@ -6,12 +6,12 @@ uniform samplerBuffer uUVW; // texture u, v, layer
uniform vec2 uViewportSize;
uniform mat4 uMatProjection;
uniform mat4 uMatModelView;
uniform float uWibbleOffset;
uniform vec2 uFog; // x = start, y = end
uniform bool uWibbleEffect;
uniform int uTime;
layout(location = 0) in vec3 inPosition;
layout(location = 1) in vec2 inDisplacement;
layout(location = 2) in int inTextureIdx;
layout(location = 2) in int inUVWIdx;
layout(location = 3) in float inShade;
out vec2 gTexUV;
@ -23,12 +23,12 @@ void main(void) {
centerEyeSpace.xy += inDisplacement;
gl_Position = uMatProjection * centerEyeSpace;
if (uWibbleOffset >= 0.0) {
if (uWibbleEffect) {
gl_Position.xyz =
waterWibble(gl_Position, uViewportSize, uWibbleOffset);
waterWibble(gl_Position, uViewportSize, uTime);
}
vec3 uvw = texelFetch(uUVW, int(inTextureIdx)).xyz;
vec3 uvw = texelFetch(uUVW, int(inUVWIdx)).xyz;
gTexUV = uvw.xy;
gTexLayer = int(uvw.z);
gShade = inShade;
@ -36,7 +36,7 @@ void main(void) {
#elif defined(FRAGMENT)
uniform sampler2DArray uTexture;
uniform sampler2DArray uTexAtlas;
uniform bool uSmoothingEnabled;
uniform float uBrightnessMultiplier;
uniform vec3 uGlobalTint;
@ -48,8 +48,8 @@ out vec4 outColor;
void main(void) {
vec3 uvw = vec3(gTexUV.x, gTexUV.y, gTexLayer);
vec4 texColor = texture(uTexture, uvw);
if (uSmoothingEnabled && discardTranslucent(uTexture, uvw)) {
vec4 texColor = texture(uTexAtlas, uvw);
if (uSmoothingEnabled && discardTranslucent(uTexAtlas, uvw)) {
discard;
}