tr1/output: make sprites use the meshes shader

This commit is contained in:
Marcin Kurczewski 2025-04-17 09:45:22 +02:00
parent 01b2d37fdc
commit f144f8ccad
6 changed files with 42 additions and 72 deletions

View file

@ -6,6 +6,7 @@
#define VERT_FLAT_SHADED 0x02
#define VERT_REFLECTIVE 0x04
#define VERT_NO_LIGHTING 0x08
#define VERT_SPRITE 0x10 // flag for billboarded sprites in mesh shader
#define WIBBLE_SIZE 32
#define MAX_WIBBLE 2

View file

@ -27,11 +27,18 @@ out float gShade;
out vec4 gColor;
void main(void) {
gWorldPos = uMatModelView * vec4(inPosition.xyz, 1.0);
// billboard sprites if flagged, else standard vertex transform
vec4 eyePos = uMatModelView * vec4(inPosition.xyz, 1.0);
if ((inFlags & VERT_SPRITE) != 0) {
// inNormal.xy carries sprite displacement for billboarding
eyePos.xy += inNormal.xy;
}
gWorldPos = eyePos;
gNormal = inNormal;
gl_Position = uMatProjection * gWorldPos;
gl_Position = uMatProjection * eyePos;
if (uWibbleEffect && (inFlags & VERT_NO_CAUSTICS) == 0) {
// apply water wibble effect only to non-sprite vertices
if (uWibbleEffect && (inFlags & VERT_NO_CAUSTICS) == 0 && (inFlags & VERT_SPRITE) == 0) {
gl_Position.xyz =
waterWibble(gl_Position, uViewportSize, uTime);
}

View file

@ -1,63 +0,0 @@
#ifdef VERTEX
uniform samplerBuffer uUVW; // texture u, v, layer
uniform vec2 uViewportSize;
uniform mat4 uMatProjection;
uniform mat4 uMatModelView;
uniform int uTime;
layout(location = 0) in vec3 inPosition;
layout(location = 1) in vec2 inDisplacement;
layout(location = 2) in vec3 inUVW;
layout(location = 3) in float inShade;
out vec4 gWorldPos;
out vec2 gTexUV;
flat out int gTexLayer;
out float gShade;
void main(void) {
vec4 centerEyeSpace = uMatModelView * vec4(inPosition, 1.0);
gWorldPos = centerEyeSpace;
centerEyeSpace.xy += inDisplacement;
gl_Position = uMatProjection * centerEyeSpace;
gTexUV = inUVW.xy;
gTexLayer = int(inUVW.z);
gShade = inShade;
}
#elif defined(FRAGMENT)
uniform sampler2DArray uTexAtlas;
uniform sampler2D uTexEnvMap;
uniform bool uSmoothingEnabled;
uniform float uBrightnessMultiplier;
uniform vec3 uGlobalTint;
uniform vec2 uFog; // x = fog start, y = fog end
in vec4 gWorldPos;
in vec2 gTexUV;
flat in int gTexLayer;
in float gShade;
out vec4 outColor;
void main(void) {
vec3 uvw = vec3(gTexUV.x, gTexUV.y, gTexLayer);
vec4 texColor = texture(uTexAtlas, uvw);
if (uSmoothingEnabled && discardTranslucent(uTexAtlas, uvw)) {
discard;
}
if (texColor.a <= 0.0) {
discard;
}
float shade = gShade;
shade = shadeFog(shade, gWorldPos.z, uFog);
texColor.rgb = applyShade(texColor.rgb, shade);
texColor.rgb *= uGlobalTint;
texColor.rgb *= uBrightnessMultiplier;
outColor = vec4(texColor.rgb, 1.0);
}
#endif

View file

@ -401,8 +401,8 @@ bool Output_Init(void)
GFX_3D_Renderer_SetAlphaPointDiscard(m_Renderer3D, true);
Output_Textures_Init();
Output_Sprites_Init();
Output_Meshes_Init();
Output_Sprites_Init();
return true;
}

View file

@ -8,6 +8,7 @@
#define VERT_FLAT_SHADED 0b0000'0010 // = 0x02
#define VERT_REFLECTIVE 0b0000'0100 // = 0x04
#define VERT_NO_LIGHTING 0b0000'1000 // = 0x08
#define VERT_SPRITE 0b0001'0000 // = 0x10
// clang-format on
typedef struct {

View file

@ -1,12 +1,15 @@
#include "game/output/sprites.h"
#include "game/output.h"
#include "game/output/meshes/common.h"
#include "game/output/shader.h"
#include "game/output/textures.h"
#include "game/output/utils.h"
#include "game/output/vertex_range.h"
#include "game/room.h"
#include <libtrx/game/math/types.h>
#include <libtrx/game/output/types.h>
#include <libtrx/gfx/gl/utils.h>
#include <libtrx/log.h>
#include <libtrx/memory.h>
@ -33,7 +36,7 @@ typedef struct {
MATRIX matrix;
XYZ_32 pos;
int32_t sprite_idx;
uint16_t shade;
M_SPRITE_SHADE shade;
} M_DYNAMIC_SPRITE;
typedef struct {
@ -135,25 +138,47 @@ static void M_PrepareBuffer(
glBindVertexArray(buffer->vao);
glBindBuffer(GL_ARRAY_BUFFER, buffer->geom_vbo);
// attribute 0: position
glEnableVertexAttribArray(0);
glVertexAttribPointer(
0, 3, GL_FLOAT, GL_FALSE, sizeof(M_SPRITE_VERTEX),
(void *)(intptr_t)offsetof(M_SPRITE_VERTEX, pos));
// attribute 1: normal (becomes sprite corner displacement)
glEnableVertexAttribArray(1);
glVertexAttribPointer(
1, 2, GL_FLOAT, GL_FALSE, sizeof(M_SPRITE_VERTEX),
(void *)(intptr_t)offsetof(M_SPRITE_VERTEX, displacement));
// attribute 2: uvw
glEnableVertexAttribArray(2);
glVertexAttribPointer(
2, 3, GL_FLOAT, GL_FALSE, sizeof(M_SPRITE_VERTEX),
(void *)(intptr_t)offsetof(M_SPRITE_VERTEX, uvw));
// attribute 3: texture size
glDisableVertexAttribArray(3);
glVertexAttrib4f(3, 0.0f, 0.0f, 1.0f, 1.0f);
// attribute 4: trapezoid ratios
glDisableVertexAttribArray(4);
glVertexAttrib2f(4, 1.0f, 1.0f);
// attribute 5: flags
glDisableVertexAttribArray(5);
glVertexAttribI1i(5, VERT_SPRITE);
// attribute 6: mesh color (ignore)
glDisableVertexAttribArray(6);
glVertexAttrib4f(6, 1.0f, 1.0f, 1.0f, 1.0f);
glBindBuffer(GL_ARRAY_BUFFER, buffer->shade_vbo);
glEnableVertexAttribArray(3);
// attribute 7 (shade)
glEnableVertexAttribArray(7);
glVertexAttribPointer(
3, 1, GL_UNSIGNED_SHORT, GL_FALSE, sizeof(M_SPRITE_SHADE), 0);
7, 1, GL_UNSIGNED_SHORT, GL_FALSE, sizeof(M_SPRITE_SHADE), 0);
}
static void M_FreeBuffer(M_SPRITE_BUFFER *const buffer)
@ -306,7 +331,7 @@ static void M_PrepareLevelBuffers(void)
void Output_Sprites_Init(void)
{
m_Shader = Output_Shader_Create("shaders/sprites.glsl");
m_Shader = Output_Meshes_GetShader();
m_LevelData.animated_vertices = Vector_Create(sizeof(OUTPUT_VERTEX_RANGE));
m_Dynamic.source = Vector_CreateAtCapacity(sizeof(M_DYNAMIC_SPRITE), 50);
}
@ -316,7 +341,6 @@ void Output_Sprites_Shutdown(void)
Vector_Free(m_LevelData.animated_vertices);
Vector_Free(m_Dynamic.source);
M_FreeBuffers();
Output_Shader_Free(m_Shader);
m_Shader = nullptr;
}