Skip to content

Commit a878d9f

Browse files
Renderer: Add ability to load additional textures like NML, PBR, etc.
1 parent deeb70a commit a878d9f

File tree

8 files changed

+123
-55
lines changed

8 files changed

+123
-55
lines changed

misc/FFNx.pcf.sh

+12-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
11
/****************************************************************************/
2+
// Copyright (C) 2009 Aali132 //
3+
// Copyright (C) 2018 quantumpencil //
4+
// Copyright (C) 2018 Maxime Bacoux //
5+
// Copyright (C) 2020 myst6re //
6+
// Copyright (C) 2020 Chris Rizzitello //
7+
// Copyright (C) 2020 John Pritchard //
28
// Copyright (C) 2021 Cosmos //
39
// //
410
// This file is part of FFNx //
@@ -13,8 +19,10 @@
1319
// GNU General Public License for more details. //
1420
/****************************************************************************/
1521

16-
SAMPLER2DSHADOW(tex_s, 3);
17-
SAMPLER2D(tex_d, 4);
22+
// TEX_S
23+
SAMPLER2DSHADOW(tex_3, 3);
24+
// TEX_D
25+
SAMPLER2D(tex_4, 4);
1826

1927
uniform mat4 invViewMatrix;
2028
uniform mat4 lightInvViewProjTexMatrix;
@@ -26,15 +34,15 @@ float sampleShadowMap(vec2 base_uv, float u, float v, float shadowMapSizeInv, fl
2634
vec2 uv = base_uv + vec2(u, v) * shadowMapSizeInv;
2735

2836
vec3 shadowUv = vec3(uv, lightDepth);
29-
float shadowFactor = shadow2D(tex_s, shadowUv);
37+
float shadowFactor = shadow2D(tex_3, shadowUv);
3038

3139
#ifdef FIELD_SHADOW
3240
#if BGFX_SHADER_LANGUAGE_HLSL > 400
3341
// Fade out shadows as the vertical distance between occluder and walkmesh increases
3442
// This is to prevent shadows being projected to multiple floors
3543

3644
float shadowDistance = 0.0;
37-
vec4 lightDepths = textureGather(tex_d, shadowUv.xy);
45+
vec4 lightDepths = textureGather(tex_4, shadowUv.xy);
3846
for(int i = 0; i < 4; ++i)
3947
{
4048
vec4 shadowPos = vec4(shadowUv.xy, lightDepths[i], 1.0);

src/common.cpp

+22-11
Original file line numberDiff line numberDiff line change
@@ -1046,21 +1046,27 @@ void common_unload_texture(struct texture_set *texture_set)
10461046
if(!VREF(texture_set, texturehandle)) return;
10471047
if(!VREF(texture_set, ogl.gl_set)) return;
10481048

1049+
struct gl_texture_set *gl_set = VREF(texture_set, ogl.gl_set);
1050+
1051+
// Destroy original static textures
10491052
for (uint32_t idx = 0; idx < VREF(texture_set, ogl.gl_set->textures); idx++)
10501053
{
1051-
if (VREF(texture_set, ogl.gl_set->is_animated))
1052-
{
1053-
// Destroy animated textures
1054-
for(std::map<uint64_t,uint32_t>::iterator it = VREF(texture_set, ogl.gl_set->animated_textures).begin(); it != VREF(texture_set, ogl.gl_set->animated_textures).end(); ++it) {
1055-
newRenderer.deleteTexture(it->second);
1056-
}
1057-
VREF(texture_set, ogl.gl_set->animated_textures).clear();
1058-
}
1059-
1060-
// Destroy original static texture
10611054
newRenderer.deleteTexture(VREF(texture_set, texturehandle[idx]));
10621055
}
10631056

1057+
// Destroy animated textures
1058+
if (gl_set->is_animated)
1059+
{
1060+
for(std::map<uint64_t,uint32_t>::iterator it = gl_set->animated_textures.begin(); it != gl_set->animated_textures.end(); ++it) {
1061+
newRenderer.deleteTexture(it->second);
1062+
}
1063+
gl_set->animated_textures.clear();
1064+
}
1065+
1066+
// Destroy additional textures
1067+
for (short slot = RendererTextureSlot::TEX_NML; slot < RendererTextureSlot::COUNT; slot++)
1068+
newRenderer.deleteTexture(gl_set->additional_textures[slot]);
1069+
10641070
external_free(VREF(texture_set, texturehandle));
10651071
delete VREF(texture_set, ogl.gl_set);
10661072

@@ -1291,7 +1297,12 @@ struct texture_set *common_load_texture(struct texture_set *_texture_set, struct
12911297
}
12921298

12931299
// allocate space for our private data
1294-
if(!VREF(texture_set, ogl.gl_set)) VRASS(texture_set, ogl.gl_set, new gl_texture_set());
1300+
if(!VREF(texture_set, ogl.gl_set))
1301+
{
1302+
VRASS(texture_set, ogl.gl_set, new gl_texture_set());
1303+
for (short slot = RendererTextureSlot::TEX_NML; slot < RendererTextureSlot::COUNT; slot++)
1304+
VRASS(texture_set, ogl.gl_set->additional_textures[slot], 0);
1305+
}
12951306

12961307
// texture handle array may not have been initialized
12971308
if(!VREF(texture_set, texturehandle))

src/gl.h

+5-2
Original file line numberDiff line numberDiff line change
@@ -86,10 +86,13 @@ struct gl_texture_set
8686
uint32_t textures;
8787
uint32_t force_filter;
8888
uint32_t force_zsort;
89+
uint32_t is_aspect_ratio_changed;
90+
// ANIMATED TEXTURES
8991
uint32_t is_animated;
9092
std::map<uint64_t, uint32_t> animated_textures;
9193
uint64_t current_animated_texture;
92-
uint32_t is_aspect_ratio_changed;
94+
// ADDITIONAL TEXTURES
95+
std::map<uint16_t, uint32_t> additional_textures;
9396
};
9497

9598
extern struct matrix d3dviewport_matrix;
@@ -122,5 +125,5 @@ bool gl_check_texture_dimensions(uint32_t width, uint32_t height, char *source);
122125
void gl_replace_texture(struct texture_set *texture_set, uint32_t palette_index, uint32_t new_texture);
123126
void gl_upload_texture(struct texture_set *texture_set, uint32_t palette_index, void *image_data, uint32_t format);
124127
void gl_bind_texture_set(struct texture_set *);
125-
void gl_set_texture(uint32_t);
128+
void gl_set_texture(uint32_t texture, struct gl_texture_set* gl_set);
126129
uint32_t gl_draw_text(uint32_t x, uint32_t y, uint32_t color, uint32_t alpha, char *fmt, ...);

src/gl/gl.cpp

+3-1
Original file line numberDiff line numberDiff line change
@@ -137,10 +137,12 @@ void gl_save_state(struct driver_state *dest)
137137
// restore complete rendering state from memory
138138
void gl_load_state(struct driver_state *src)
139139
{
140+
VOBJ(texture_set, texture_set, src->texture_set);
141+
140142
memcpy(&current_state, src, sizeof(current_state));
141143

142144
gl_bind_texture_set(src->texture_set);
143-
gl_set_texture(src->texture_handle);
145+
gl_set_texture(src->texture_handle, src->texture_set ? VREF(texture_set, ogl.gl_set) : NULL);
144146
current_state.texture_set = src->texture_set;
145147
common_setviewport(src->viewport[0], src->viewport[1], src->viewport[2], src->viewport[3], 0);
146148
gl_set_blend_func(src->blend_mode);

src/gl/texture.cpp

+13-6
Original file line numberDiff line numberDiff line change
@@ -101,28 +101,35 @@ void gl_bind_texture_set(struct texture_set *_texture_set)
101101
struct gl_texture_set* gl_set = VREF(texture_set, ogl.gl_set);
102102

103103
if (gl_set->is_animated && VREF(texture_set, ogl.external))
104-
{
105-
gl_set_texture(gl_set->animated_textures[gl_set->current_animated_texture]);
106-
}
104+
newRenderer.useTexture(gl_set->animated_textures[gl_set->current_animated_texture]);
107105
else
108-
gl_set_texture(VREF(texture_set, texturehandle[VREF(tex_header, palette_index)]));
106+
gl_set_texture(VREF(texture_set, texturehandle[VREF(tex_header, palette_index)]), gl_set);
109107

110108
if(VREF(tex_header, version) == FB_TEX_VERSION) current_state.fb_texture = true;
111109
else current_state.fb_texture = false;
112110
}
113-
else gl_set_texture(0);
111+
else gl_set_texture(0, NULL);
114112

115113
current_state.texture_set = _texture_set;
116114
}
117115

118116
// prepare an OpenGL texture for rendering, passing zero to this function will
119117
// disable texturing entirely
120-
void gl_set_texture(uint32_t texture)
118+
void gl_set_texture(uint32_t texture, struct gl_texture_set* gl_set)
121119
{
122120
if(trace_all) ffnx_trace("gl_set_texture: set texture %i\n", texture);
123121

124122
newRenderer.useTexture(texture);
125123

124+
// Attach additional textures
125+
for (short slot = RendererTextureSlot::TEX_NML; slot < RendererTextureSlot::COUNT; slot++)
126+
{
127+
if (texture > 0 && gl_set)
128+
newRenderer.useTexture(gl_set->additional_textures[slot], slot);
129+
else
130+
newRenderer.useTexture(0, slot);
131+
}
132+
126133
current_state.texture_handle = texture;
127134
current_state.texture_set = 0;
128135
}

src/renderer.cpp

+37-30
Original file line numberDiff line numberDiff line change
@@ -552,44 +552,49 @@ void Renderer::bindTextures()
552552
{
553553
if (!internalState.bTexturesBound)
554554
{
555-
// slots 0-2
555+
for (uint32_t idx = RendererTextureSlot::TEX_Y; idx < RendererTextureSlot::COUNT; idx++)
556556
{
557-
uint32_t idxMax = 3;
557+
bgfx::TextureHandle handle = internalState.texHandlers[idx];
558558

559-
for (uint32_t idx = RendererTextureSlot::TEX_Y; idx <= RendererTextureSlot::TEX_V; idx++)
559+
if (bgfx::isValid(handle))
560560
{
561-
bgfx::TextureHandle handle = internalState.texHandlers[idx];
561+
uint32_t flags = 0;
562562

563-
if (!internalState.bIsMovie && idx > 0) handle = BGFX_INVALID_HANDLE;
564-
565-
if (bgfx::isValid(handle))
563+
switch(idx)
566564
{
567-
uint32_t flags = 0;
568-
569-
if (backendProgram == RendererProgram::POSTPROCESSING)
570-
{
571-
flags = BGFX_SAMPLER_U_CLAMP | BGFX_SAMPLER_V_CLAMP | BGFX_SAMPLER_W_CLAMP | BGFX_SAMPLER_MIN_ANISOTROPIC | BGFX_SAMPLER_MAG_ANISOTROPIC;
572-
}
573-
else
574-
{
575-
if (internalState.bIsMovie) flags |= BGFX_SAMPLER_U_CLAMP | BGFX_SAMPLER_V_CLAMP | BGFX_SAMPLER_W_CLAMP;
576-
577-
if (!internalState.bDoTextureFiltering || !internalState.bIsExternalTexture) flags |= BGFX_SAMPLER_MIN_POINT | BGFX_SAMPLER_MAG_POINT | BGFX_SAMPLER_MIP_POINT;
565+
case RendererTextureSlot::TEX_Y:
566+
case RendererTextureSlot::TEX_U:
567+
case RendererTextureSlot::TEX_V:
568+
if (!internalState.bIsMovie && idx > RendererTextureSlot::TEX_Y) handle = BGFX_INVALID_HANDLE;
569+
570+
if (backendProgram == RendererProgram::POSTPROCESSING)
571+
{
572+
flags = BGFX_SAMPLER_U_CLAMP | BGFX_SAMPLER_V_CLAMP | BGFX_SAMPLER_W_CLAMP | BGFX_SAMPLER_MIN_ANISOTROPIC | BGFX_SAMPLER_MAG_ANISOTROPIC;
573+
}
574+
else
575+
{
576+
if (internalState.bIsMovie) flags |= BGFX_SAMPLER_U_CLAMP | BGFX_SAMPLER_V_CLAMP | BGFX_SAMPLER_W_CLAMP;
577+
578+
if (!internalState.bDoTextureFiltering || !internalState.bIsExternalTexture) flags |= BGFX_SAMPLER_MIN_POINT | BGFX_SAMPLER_MAG_POINT | BGFX_SAMPLER_MIP_POINT;
579+
}
580+
break;
581+
case RendererTextureSlot::TEX_S:
582+
handle = bgfx::getTexture(shadowMapFrameBuffer);
583+
break;
584+
case RendererTextureSlot::TEX_D:
585+
handle = bgfx::getTexture(shadowMapFrameBuffer);
586+
flags |= BGFX_TEXTURE_RT | BGFX_SAMPLER_POINT | BGFX_SAMPLER_U_CLAMP | BGFX_SAMPLER_V_CLAMP | BGFX_SAMPLER_W_CLAMP;
587+
break;
588+
default:
589+
break;
590+
}
578591

579-
if (flags == 0) flags = UINT32_MAX;
580-
}
592+
if (flags == 0) flags = UINT32_MAX;
581593

582-
bgfx::setTexture(idx, getUniform("tex_" + std::to_string(idx), bgfx::UniformType::Sampler), handle, flags);
583-
}
594+
bgfx::setTexture(idx, getUniform("tex_" + std::to_string(idx), bgfx::UniformType::Sampler), handle, flags);
584595
}
585596
}
586597

587-
// slot 3: shadow map with comparison sampler
588-
bgfx::setTexture(RendererTextureSlot::TEX_S, getUniform("tex_" + std::to_string(RendererTextureSlot::TEX_S), bgfx::UniformType::Sampler), bgfx::getTexture(shadowMapFrameBuffer));
589-
590-
// slot 4: shadow map for direct depth sampling
591-
bgfx::setTexture(RendererTextureSlot::TEX_D, getUniform("tex_" + std::to_string(RendererTextureSlot::TEX_D), bgfx::UniformType::Sampler), bgfx::getTexture(shadowMapFrameBuffer), BGFX_TEXTURE_RT | BGFX_SAMPLER_POINT | BGFX_SAMPLER_U_CLAMP | BGFX_SAMPLER_V_CLAMP | BGFX_SAMPLER_W_CLAMP);
592-
593598
internalState.bTexturesBound = true;
594599
}
595600
}
@@ -619,6 +624,8 @@ void Renderer::init()
619624

620625
if (!bgfx::init(bgfxInit)) exit(1);
621626

627+
internalState.texHandlers.resize(RendererTextureSlot::COUNT, BGFX_INVALID_HANDLE);
628+
622629
updateRendererShaderPaths();
623630

624631
bx::mtxOrtho(
@@ -1398,12 +1405,12 @@ void Renderer::useTexture(uint16_t rt, uint32_t slot)
13981405
if (rt > 0)
13991406
{
14001407
internalState.texHandlers[slot] = { rt };
1401-
isTexture(true);
1408+
if (slot == RendererTextureSlot::TEX_Y) isTexture(true);
14021409
}
14031410
else
14041411
{
14051412
internalState.texHandlers[slot] = BGFX_INVALID_HANDLE;
1406-
isTexture(false);
1413+
if (slot == RendererTextureSlot::TEX_Y) isTexture(false);
14071414
}
14081415
};
14091416

src/renderer.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,8 @@ enum RendererTextureSlot
101101
TEX_V,
102102
TEX_S,
103103
TEX_D,
104+
TEX_NML,
105+
TEX_PBR,
104106
COUNT
105107
};
106108

@@ -177,7 +179,7 @@ class Renderer {
177179

178180
struct RendererState
179181
{
180-
bgfx::TextureHandle texHandlers[3];
182+
std::vector<bgfx::TextureHandle> texHandlers;
181183
bool bTexturesBound = false;
182184

183185
bool bHasDrawBeenDone = false;

src/saveload.cpp

+28
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,11 @@
3030

3131
#include "discohash.h"
3232

33+
std::map<uint16_t, std::string> additional_textures = {
34+
{RendererTextureSlot::TEX_NML, "nml"},
35+
{RendererTextureSlot::TEX_PBR, "pbr"}
36+
};
37+
3338
void make_path(char *name)
3439
{
3540
char *next = name;
@@ -172,6 +177,29 @@ uint32_t load_texture(void* data, uint32_t dataSize, char* name, uint32_t palett
172177
else
173178
{
174179
if (trace_all) ffnx_trace("Created external texture: %u from %s\n", ret, filename);
180+
181+
if (!is_animated)
182+
{
183+
// Load additional textures
184+
for (const auto& it : additional_textures)
185+
{
186+
for (int idx = 0; idx < mod_ext.size(); idx++)
187+
{
188+
_snprintf(filename, sizeof(filename), "%s/%s/%s_%02i_%s.%s", basedir, mod_path.c_str(), name, palette_index, it.second.c_str(), mod_ext[idx].c_str());
189+
190+
if (stat(filename, &dummy) == 0)
191+
{
192+
if (gl_set->additional_textures.count(it.first)) newRenderer.deleteTexture(gl_set->additional_textures[it.first]);
193+
gl_set->additional_textures[it.first] = load_texture_helper(filename, width, height, mod_ext[idx] == "png");
194+
break;
195+
}
196+
else if (trace_all || show_missing_textures)
197+
{
198+
ffnx_trace("Could not find [ %s ].\n", filename);
199+
}
200+
}
201+
}
202+
}
175203
}
176204

177205
if (is_animated) gl_set->current_animated_texture = hash;

0 commit comments

Comments
 (0)