mirror of
https://github.com/LostArtefacts/TRX.git
synced 2025-04-28 12:47:58 +03:00
tr1/output: improve bilinear filter UVs
This commit is contained in:
parent
d647539581
commit
ebe743cb0e
8 changed files with 101 additions and 17 deletions
|
@ -2,6 +2,7 @@
|
|||
|
||||
uniform int uTime;
|
||||
uniform samplerBuffer uUVW; // texture u, v, layer
|
||||
uniform samplerBuffer uAtlasSizes; // texture x, y, w, h
|
||||
uniform vec2 uViewportSize;
|
||||
uniform mat4 uMatProjection;
|
||||
uniform mat4 uMatModelView;
|
||||
|
@ -21,6 +22,7 @@ out vec3 gNormal;
|
|||
flat out int gFlags;
|
||||
flat out int gTexLayer;
|
||||
out vec2 gTexUV;
|
||||
flat out vec4 gAtlasSize;
|
||||
out vec2 gTrapezoidRatios;
|
||||
out float gShade;
|
||||
out vec4 gColor;
|
||||
|
@ -36,6 +38,7 @@ void main(void) {
|
|||
}
|
||||
|
||||
vec3 uvw = texelFetch(uUVW, int(inUVWIdx)).xyz;
|
||||
gAtlasSize = texelFetch(uAtlasSizes, int(inUVWIdx / 4));
|
||||
gFlags = inFlags;
|
||||
gTexLayer = int(uvw.z);
|
||||
gTexUV = uvw.xy;
|
||||
|
@ -67,14 +70,22 @@ in vec3 gNormal;
|
|||
flat in int gFlags;
|
||||
flat in int gTexLayer;
|
||||
in vec2 gTexUV;
|
||||
flat in vec4 gAtlasSize;
|
||||
in float gShade;
|
||||
in vec4 gColor;
|
||||
in vec2 gTrapezoidRatios;
|
||||
out vec4 outColor;
|
||||
|
||||
vec2 clampTexAtlas(vec2 uv, vec4 atlasSize)
|
||||
{
|
||||
float epsilon = 0.5 / 256.0;
|
||||
return clamp(uv, atlasSize.xy + epsilon, atlasSize.zw - epsilon);
|
||||
}
|
||||
|
||||
void main(void) {
|
||||
vec4 texColor = gColor;
|
||||
vec3 texCoords = vec3(gTexUV.x, gTexUV.y, gTexLayer);
|
||||
texCoords.xy = clampTexAtlas(gTexUV.xy / gTrapezoidRatios.xy, gAtlasSize) * gTrapezoidRatios.xy;
|
||||
if (uTrapezoidFilterEnabled) {
|
||||
texCoords.xy /= gTrapezoidRatios.xy;
|
||||
}
|
||||
|
|
|
@ -89,6 +89,5 @@ void Output_DisableScissor(void);
|
|||
void Output_RememberState(void);
|
||||
void Output_RestoreState(void);
|
||||
|
||||
float Output_AdjustUV(uint16_t uv);
|
||||
int32_t Output_GetLightDivider(void);
|
||||
XYZ_32 Output_GetLightVectorView(void);
|
||||
|
|
|
@ -16,17 +16,8 @@ static struct {
|
|||
} m_CachedState;
|
||||
|
||||
static bool m_IsSkyboxEnabled = false;
|
||||
static inline float M_GetUV(uint16_t uv);
|
||||
static void M_DrawSphere(XYZ_32 pos, int32_t radius);
|
||||
|
||||
static inline float M_GetUV(const uint16_t uv)
|
||||
{
|
||||
return g_Config.rendering.pretty_pixels
|
||||
&& g_Config.rendering.texture_filter == GFX_TF_NN
|
||||
? uv / 65536.0f
|
||||
: ((uv & 0xFF00) + 127) / 65536.0f;
|
||||
}
|
||||
|
||||
static void M_DrawSphere(const XYZ_32 pos, const int32_t radius)
|
||||
{
|
||||
// More subdivisions means smoother spheres.
|
||||
|
@ -92,11 +83,6 @@ static void M_DrawSphere(const XYZ_32 pos, const int32_t radius)
|
|||
glPolygonMode(GL_FRONT_AND_BACK, m_CachedState.bound_polygon_mode[0]);
|
||||
}
|
||||
|
||||
float Output_AdjustUV(const uint16_t uv)
|
||||
{
|
||||
return M_GetUV(uv);
|
||||
}
|
||||
|
||||
void Output_SetSkyboxEnabled(const bool enabled)
|
||||
{
|
||||
m_IsSkyboxEnabled = enabled;
|
||||
|
|
|
@ -424,6 +424,8 @@ void Output_Meshes_RenderObjectMesh(
|
|||
glBindTexture(GL_TEXTURE_BUFFER, Output_Textures_GetObjectUVWsTexture());
|
||||
glActiveTexture(GL_TEXTURE2);
|
||||
glBindTexture(GL_TEXTURE_2D, Output_Textures_GetEnvMapTexture());
|
||||
glActiveTexture(GL_TEXTURE3);
|
||||
glBindTexture(GL_TEXTURE_BUFFER, Output_Textures_GetAtlasSizesTexture());
|
||||
GFX_GL_CheckError();
|
||||
|
||||
Output_Shader_UploadWibbleEffect(m_Shader, false);
|
||||
|
|
|
@ -314,6 +314,8 @@ void Output_Meshes_RenderRoomMesh(
|
|||
glBindTexture(GL_TEXTURE_BUFFER, Output_Textures_GetObjectUVWsTexture());
|
||||
glActiveTexture(GL_TEXTURE2);
|
||||
glBindTexture(GL_TEXTURE_2D, Output_Textures_GetEnvMapTexture());
|
||||
glActiveTexture(GL_TEXTURE3);
|
||||
glBindTexture(GL_TEXTURE_BUFFER, Output_Textures_GetAtlasSizesTexture());
|
||||
GFX_GL_CheckError();
|
||||
|
||||
if (Output_GetWibbleEffect()) {
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
typedef enum {
|
||||
M_UNIFORM_TIME,
|
||||
M_UNIFORM_TEX_ATLAS,
|
||||
M_UNIFORM_TEX_ATLAS_SIZES,
|
||||
M_UNIFORM_TEX_UVW,
|
||||
M_UNIFORM_TEX_ENV_MAP,
|
||||
M_UNIFORM_SMOOTHING_ENABLED,
|
||||
|
@ -51,6 +52,7 @@ OUTPUT_SHADER *Output_Shader_Create(const char *const path)
|
|||
const char *const uniform_names[] = {
|
||||
[M_UNIFORM_TIME] = "uTime",
|
||||
[M_UNIFORM_TEX_ATLAS] = "uTexAtlas",
|
||||
[M_UNIFORM_TEX_ATLAS_SIZES] = "uAtlasSizes",
|
||||
[M_UNIFORM_TEX_UVW] = "uUVW",
|
||||
[M_UNIFORM_TEX_ENV_MAP] = "uTexEnvMap",
|
||||
[M_UNIFORM_SMOOTHING_ENABLED] = "uSmoothingEnabled",
|
||||
|
@ -77,6 +79,7 @@ OUTPUT_SHADER *Output_Shader_Create(const char *const path)
|
|||
glUniform1i(shader->uniforms[M_UNIFORM_TEX_ATLAS], 0);
|
||||
glUniform1i(shader->uniforms[M_UNIFORM_TEX_UVW], 1);
|
||||
glUniform1i(shader->uniforms[M_UNIFORM_TEX_ENV_MAP], 2);
|
||||
glUniform1i(shader->uniforms[M_UNIFORM_TEX_ATLAS_SIZES], 3);
|
||||
return shader;
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,12 @@
|
|||
|
||||
#include <stdlib.h>
|
||||
|
||||
#pragma pack(push, 1)
|
||||
typedef struct {
|
||||
float x0, y0, x1, y1;
|
||||
} M_ATLAS_SIZE;
|
||||
#pragma pack(pop)
|
||||
|
||||
typedef struct {
|
||||
int32_t index;
|
||||
int32_t count;
|
||||
|
@ -45,6 +51,11 @@ static struct {
|
|||
GLuint tex_env_map;
|
||||
M_TEXTURE_DATA objects;
|
||||
M_TEXTURE_DATA sprites;
|
||||
struct {
|
||||
GLuint tex;
|
||||
GLuint tbo;
|
||||
M_ATLAS_SIZE *data;
|
||||
} atlas_sizes;
|
||||
} m_Priv = {};
|
||||
|
||||
static int M_CompareAnimationRange(const void *const a, const void *const b)
|
||||
|
@ -170,13 +181,33 @@ static void M_FreeTextureData(M_TEXTURE_DATA *const data)
|
|||
}
|
||||
}
|
||||
|
||||
static void M_FillAtlasSize(const int32_t i)
|
||||
{
|
||||
M_ATLAS_SIZE *size = &m_Priv.atlas_sizes.data[i];
|
||||
const OBJECT_TEXTURE *const texture = Output_GetObjectTexture(i);
|
||||
size->x0 = texture->uv[0].u;
|
||||
size->y0 = texture->uv[0].v;
|
||||
size->x1 = texture->uv[0].u;
|
||||
size->y1 = texture->uv[0].v;
|
||||
for (int32_t j = 1; j < 3; j++) {
|
||||
size->x0 = MIN(size->x0, texture->uv[j].u);
|
||||
size->y0 = MIN(size->y0, texture->uv[j].v);
|
||||
size->x1 = MAX(size->x1, texture->uv[j].u);
|
||||
size->y1 = MAX(size->y1, texture->uv[j].v);
|
||||
}
|
||||
size->x0 /= 65535.0;
|
||||
size->y0 /= 65535.0;
|
||||
size->x1 /= 65535.0;
|
||||
size->y1 /= 65535.0;
|
||||
}
|
||||
|
||||
static void M_FillObjectUVW(const int32_t i)
|
||||
{
|
||||
const OBJECT_TEXTURE *const texture = Output_GetObjectTexture(i);
|
||||
M_UVW *const corners = m_Priv.objects.uvw[i].corners;
|
||||
for (int32_t j = 0; j < 4; j++) {
|
||||
corners[j].u = Output_AdjustUV(texture->uv[j].u);
|
||||
corners[j].v = Output_AdjustUV(texture->uv[j].v);
|
||||
corners[j].u = texture->uv[j].u / 65535.0f;
|
||||
corners[j].v = texture->uv[j].v / 65535.0f;
|
||||
corners[j].w = texture->tex_page;
|
||||
}
|
||||
}
|
||||
|
@ -245,6 +276,19 @@ static void M_UploadObjectAnimatedUVWs(const M_ANIMATION_RANGES *const source)
|
|||
range->count * sizeof(M_UVW_PACK),
|
||||
m_Priv.objects.uvw + range->index);
|
||||
}
|
||||
|
||||
glBindBuffer(GL_TEXTURE_BUFFER, m_Priv.atlas_sizes.tbo);
|
||||
for (int32_t i = 0; i < source->range_count; i++) {
|
||||
const M_ANIMATION_RANGE *const range = &source->ranges[i];
|
||||
for (int32_t j = 0; j < range->count; j++) {
|
||||
M_FillAtlasSize(range->index + j);
|
||||
}
|
||||
GFX_TRACK_DATA(
|
||||
glBufferSubData, GL_TEXTURE_BUFFER,
|
||||
range->index * sizeof(M_ATLAS_SIZE),
|
||||
range->count * sizeof(M_ATLAS_SIZE),
|
||||
m_Priv.atlas_sizes.data + range->index);
|
||||
}
|
||||
}
|
||||
|
||||
static void M_UploadSpriteAnimatedUVWs(const M_ANIMATION_RANGES *const source)
|
||||
|
@ -304,6 +348,24 @@ static void M_PrepareEnvMap(void)
|
|||
GFX_GL_CheckError();
|
||||
}
|
||||
|
||||
static void M_PrepareAtlasSizes(void)
|
||||
{
|
||||
glGenBuffers(1, &m_Priv.atlas_sizes.tbo);
|
||||
glBindBuffer(GL_TEXTURE_BUFFER, m_Priv.atlas_sizes.tbo);
|
||||
glGenTextures(1, &m_Priv.atlas_sizes.tex);
|
||||
glBindTexture(GL_TEXTURE_BUFFER, m_Priv.atlas_sizes.tex);
|
||||
glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, m_Priv.atlas_sizes.tbo);
|
||||
const int32_t count = Output_GetObjectTextureCount();
|
||||
m_Priv.atlas_sizes.data =
|
||||
Memory_Realloc(m_Priv.atlas_sizes.data, count * sizeof(M_ATLAS_SIZE));
|
||||
for (int32_t i = 0; i < count; i++) {
|
||||
M_FillAtlasSize(i);
|
||||
}
|
||||
GFX_TRACK_DATA(
|
||||
glBufferData, GL_TEXTURE_BUFFER, count * sizeof(M_ATLAS_SIZE),
|
||||
m_Priv.atlas_sizes.data, GL_DYNAMIC_DRAW);
|
||||
}
|
||||
|
||||
static void M_UploadAtlas(void)
|
||||
{
|
||||
glGenTextures(1, &m_Priv.tex_atlas);
|
||||
|
@ -335,6 +397,10 @@ static void M_UploadAtlas(void)
|
|||
GL_RGBA, GL_UNSIGNED_BYTE, input_ptr);
|
||||
}
|
||||
GFX_GL_CheckError();
|
||||
|
||||
M_PrepareAtlasSizes();
|
||||
|
||||
GFX_GL_CheckError();
|
||||
}
|
||||
|
||||
static void M_FreeLevelData(void)
|
||||
|
@ -347,6 +413,15 @@ static void M_FreeLevelData(void)
|
|||
glDeleteTextures(1, &m_Priv.tex_atlas);
|
||||
m_Priv.tex_atlas = 0;
|
||||
}
|
||||
if (m_Priv.atlas_sizes.tex != 0) {
|
||||
glDeleteTextures(1, &m_Priv.atlas_sizes.tex);
|
||||
m_Priv.atlas_sizes.tex = 0;
|
||||
}
|
||||
if (m_Priv.atlas_sizes.tbo != 0) {
|
||||
glDeleteBuffers(1, &m_Priv.atlas_sizes.tbo);
|
||||
m_Priv.atlas_sizes.tbo = 0;
|
||||
}
|
||||
Memory_FreePointer(&m_Priv.atlas_sizes.data);
|
||||
Memory_FreePointer(&m_AnimationRanges.objects.ranges);
|
||||
Memory_FreePointer(&m_AnimationRanges.sprites.ranges);
|
||||
}
|
||||
|
@ -423,6 +498,11 @@ GLuint Output_Textures_GetAtlasTexture(void)
|
|||
return m_Priv.tex_atlas;
|
||||
}
|
||||
|
||||
GLuint Output_Textures_GetAtlasSizesTexture(void)
|
||||
{
|
||||
return m_Priv.atlas_sizes.tex;
|
||||
}
|
||||
|
||||
GLuint Output_Textures_GetEnvMapTexture(void)
|
||||
{
|
||||
return m_Priv.tex_env_map;
|
||||
|
|
|
@ -11,4 +11,5 @@ void Output_Textures_ApplyRenderSettings(void);
|
|||
GLuint Output_Textures_GetObjectUVWsTexture(void);
|
||||
GLuint Output_Textures_GetSpriteUVWsTexture(void);
|
||||
GLuint Output_Textures_GetAtlasTexture(void);
|
||||
GLuint Output_Textures_GetAtlasSizesTexture(void);
|
||||
GLuint Output_Textures_GetEnvMapTexture(void);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue