gfx: generate brdf lut
parent
b94c56ec58
commit
ff72ac6bc9
|
@ -0,0 +1,100 @@
|
||||||
|
#version 400
|
||||||
|
const float PI = 3.1415926536;
|
||||||
|
|
||||||
|
in vec2 uv;
|
||||||
|
out vec2 fragcolor;
|
||||||
|
|
||||||
|
float RadicalInverse_VdC(uint bits) {
|
||||||
|
bits = (bits << 16u) | (bits >> 16u);
|
||||||
|
bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);
|
||||||
|
bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);
|
||||||
|
bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);
|
||||||
|
bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);
|
||||||
|
return float(bits) * 2.3283064365386963e-10; // / 0x100000000
|
||||||
|
}
|
||||||
|
|
||||||
|
vec2 Hammersley(uint i, uint N) {
|
||||||
|
return vec2(float(i)/float(N), RadicalInverse_VdC(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 ImportanceSampleGGX(vec2 Xi, vec3 N, float roughness) {
|
||||||
|
float a = roughness*roughness;
|
||||||
|
|
||||||
|
float phi = 2.0 * PI * Xi.x;
|
||||||
|
float cosTheta = sqrt((1.0 - Xi.y) / (1.0 + (a*a - 1.0) * Xi.y));
|
||||||
|
float sinTheta = sqrt(1.0 - cosTheta*cosTheta);
|
||||||
|
|
||||||
|
// from spherical coordinates to cartesian coordinates
|
||||||
|
vec3 H;
|
||||||
|
H.x = cos(phi) * sinTheta;
|
||||||
|
H.y = sin(phi) * sinTheta;
|
||||||
|
H.z = cosTheta;
|
||||||
|
|
||||||
|
// from tangent-space vector to world-space sample vector
|
||||||
|
vec3 up = abs(N.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0);
|
||||||
|
vec3 tangent = normalize(cross(up, N));
|
||||||
|
vec3 bitangent = cross(N, tangent);
|
||||||
|
|
||||||
|
vec3 sampleVec = tangent * H.x + bitangent * H.y + N * H.z;
|
||||||
|
return normalize(sampleVec);
|
||||||
|
}
|
||||||
|
|
||||||
|
float GeometrySchlickGGX(float NdotV, float roughness) {
|
||||||
|
float a = roughness;
|
||||||
|
float k = (a * a) / 2.0;
|
||||||
|
|
||||||
|
float nom = NdotV;
|
||||||
|
float denom = NdotV * (1.0 - k) + k;
|
||||||
|
|
||||||
|
return nom / denom;
|
||||||
|
}
|
||||||
|
|
||||||
|
float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness) {
|
||||||
|
float NdotV = max(dot(N, V), 0.0);
|
||||||
|
float NdotL = max(dot(N, L), 0.0);
|
||||||
|
float ggx2 = GeometrySchlickGGX(NdotV, roughness);
|
||||||
|
float ggx1 = GeometrySchlickGGX(NdotL, roughness);
|
||||||
|
|
||||||
|
return ggx1 * ggx2;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec2 GenerateBRDF(float NdotV, float roughness) {
|
||||||
|
vec3 V;
|
||||||
|
V.x = sqrt(1.0 - NdotV*NdotV);
|
||||||
|
V.y = 0.0;
|
||||||
|
V.z = NdotV;
|
||||||
|
|
||||||
|
float A = 0.0;
|
||||||
|
float B = 0.0;
|
||||||
|
|
||||||
|
vec3 N = vec3(0.0, 0.0, 1.0);
|
||||||
|
|
||||||
|
const uint SAMPLE_COUNT = 1024u;
|
||||||
|
for(uint i = 0u; i < SAMPLE_COUNT; ++i)
|
||||||
|
{
|
||||||
|
vec2 Xi = Hammersley(i, SAMPLE_COUNT);
|
||||||
|
vec3 H = ImportanceSampleGGX(Xi, N, roughness);
|
||||||
|
vec3 L = normalize(2.0 * dot(V, H) * H - V);
|
||||||
|
|
||||||
|
float NdotL = max(L.z, 0.0);
|
||||||
|
float NdotH = max(H.z, 0.0);
|
||||||
|
float VdotH = max(dot(V, H), 0.0);
|
||||||
|
|
||||||
|
if(NdotL > 0.0)
|
||||||
|
{
|
||||||
|
float G = GeometrySmith(N, V, L, roughness);
|
||||||
|
float G_Vis = (G * VdotH) / (NdotH * NdotV);
|
||||||
|
float Fc = pow(1.0 - VdotH, 5.0);
|
||||||
|
|
||||||
|
A += (1.0 - Fc) * G_Vis;
|
||||||
|
B += Fc * G_Vis;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
A /= float(SAMPLE_COUNT);
|
||||||
|
B /= float(SAMPLE_COUNT);
|
||||||
|
return vec2(A, B);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
fragcolor = GenerateBRDF(uv.x, uv.y);
|
||||||
|
}
|
|
@ -227,7 +227,7 @@ float geometry_smith( vec3 N, vec3 V, vec3 L, float roughness )
|
||||||
vec2 sphere_to_polar( vec3 normal )
|
vec2 sphere_to_polar( vec3 normal )
|
||||||
{
|
{
|
||||||
normal = normalize( normal );
|
normal = normalize( normal );
|
||||||
return vec2( ( atan( normal.z, normal.x ) + skysphere_rotation ) / PI / 2.0 + 0.5, acos( normal.y ) / PI );
|
return vec2( ( atan( normal.z, normal.x ) - PI*0.5f ) / PI / 2.0 + 0.5, acos( normal.y ) / PI );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Our vertically GL_CLAMPed textures seem to blend towards black when sampling the half-pixel edge.
|
// Our vertically GL_CLAMPed textures seem to blend towards black when sampling the half-pixel edge.
|
||||||
|
@ -285,7 +285,7 @@ vec3 sample_irradiance_fast( vec3 normal, vec3 vertex_tangent )
|
||||||
// Sample the irradiance map if it exists, otherwise fall back to blurred reflection map.
|
// Sample the irradiance map if it exists, otherwise fall back to blurred reflection map.
|
||||||
if ( has_tex_skyenv )
|
if ( has_tex_skyenv )
|
||||||
{
|
{
|
||||||
vec2 polar = sphere_to_polar_clamp_y( normal, 180.0 );
|
vec2 polar = sphere_to_polar( normal );
|
||||||
return textureLod( tex_skyenv, polar, 0.0 ).rgb * exposure;
|
return textureLod( tex_skyenv, polar, 0.0 ).rgb * exposure;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -473,7 +473,7 @@ void main(void)
|
||||||
}
|
}
|
||||||
else if( map_roughness.has_tex ) {
|
else if( map_roughness.has_tex ) {
|
||||||
//< @r-lyeh, metalness B, roughness G, (@todo: self-shadowing occlusion R; for now, any of R/B are metallic)
|
//< @r-lyeh, metalness B, roughness G, (@todo: self-shadowing occlusion R; for now, any of R/B are metallic)
|
||||||
metallic = sample_colormap( map_roughness, v_texcoord ).b + sample_colormap( map_roughness, v_texcoord ).r;
|
metallic = sample_colormap( map_roughness, v_texcoord ).b;// + sample_colormap( map_roughness, v_texcoord ).r;
|
||||||
roughness = sample_colormap( map_roughness, v_texcoord ).g;
|
roughness = sample_colormap( map_roughness, v_texcoord ).g;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -708,21 +708,6 @@ void main(void)
|
||||||
// Technically this alpha may be too transparent, if there is a lot of reflected light we wouldn't
|
// Technically this alpha may be too transparent, if there is a lot of reflected light we wouldn't
|
||||||
// see the background, maybe we can approximate it well enough by adding a fresnel term
|
// see the background, maybe we can approximate it well enough by adding a fresnel term
|
||||||
fragcolor = vec4( color * shadowing().xyz, alpha );
|
fragcolor = vec4( color * shadowing().xyz, alpha );
|
||||||
|
|
||||||
// rimlight
|
|
||||||
#ifdef RIM
|
|
||||||
{
|
|
||||||
vec3 n = normalize(mat3(M) * v_normal_ws); // convert normal to view space
|
|
||||||
vec3 p = (M * vec4(v_position,1.0)).xyz; // convert position to view space
|
|
||||||
vec3 v = vec3(0,-1,0);
|
|
||||||
if (!u_rimambient) {
|
|
||||||
v = normalize(u_rimpivot-p);
|
|
||||||
}
|
|
||||||
float rim = 1.0 - max(dot(v,n), 0.0);
|
|
||||||
vec3 col = u_rimcolor*(pow(smoothstep(1.0-u_rimrange.x,u_rimrange.y,rim), u_rimrange.z));
|
|
||||||
fragcolor += vec4(col, 0.0);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -371199,6 +371199,9 @@ texture_t texture_compressed_from_mem(const void *data, int len, unsigned flags)
|
||||||
if( dimensions > 0 ) glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
if( dimensions > 0 ) glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||||
if( dimensions > 1 ) glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
if( dimensions > 1 ) glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||||
if( dimensions > 2 ) glTexParameteri(target, GL_TEXTURE_WRAP_R, GL_REPEAT);
|
if( dimensions > 2 ) glTexParameteri(target, GL_TEXTURE_WRAP_R, GL_REPEAT);
|
||||||
|
if( flags&TEXTURE_CLAMP && dimensions > 0 ) glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
|
if( flags&TEXTURE_CLAMP && dimensions > 1 ) glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
|
if( flags&TEXTURE_CLAMP && dimensions > 2 ) glTexParameteri(target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
||||||
|
|
||||||
if( target == GL_TEXTURE_CUBE_MAP ) target = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
|
if( target == GL_TEXTURE_CUBE_MAP ) target = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
|
||||||
|
|
||||||
|
@ -372620,15 +372623,55 @@ int ui_fxs() {
|
||||||
static texture_t brdf = {0};
|
static texture_t brdf = {0};
|
||||||
|
|
||||||
static void brdf_load() {
|
static void brdf_load() {
|
||||||
const char *filename;
|
// generate texture
|
||||||
filename = "Skyboxes/brdf_lut1k_256x256_32F.ktx";
|
unsigned tex;
|
||||||
filename = "Skyboxes/brdf_lut2k_512x512_32F.ktx";
|
glGenTextures(1, &tex);
|
||||||
|
|
||||||
brdf = texture_compressed( filename,
|
glBindTexture(GL_TEXTURE_2D, tex);
|
||||||
TEXTURE_CLAMP | TEXTURE_NEAREST | TEXTURE_RG | TEXTURE_FLOAT
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RG16F, 512, 512, 0, GL_RG, GL_FLOAT, 0);
|
||||||
);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
unsigned texchecker = texture_checker().id;
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
ASSERT(brdf.id != texchecker, "!Couldn't load BRDF lookup table '%s'!", filename );
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
|
||||||
|
brdf.id = tex;
|
||||||
|
brdf.w = 512;
|
||||||
|
brdf.h = 512;
|
||||||
|
|
||||||
|
// create program and generate BRDF LUT
|
||||||
|
unsigned lut_fbo = fbo(tex, 0, 0), rbo=0;
|
||||||
|
fbo_bind(lut_fbo);
|
||||||
|
|
||||||
|
static int program = -1, vao = -1;
|
||||||
|
if( program < 0 ) {
|
||||||
|
const char* vs = vfs_read("shaders/vs_0_2_fullscreen_quad_B_flipped.glsl");
|
||||||
|
const char* fs = vfs_read("shaders/brdf.glsl");
|
||||||
|
|
||||||
|
program = shader(vs, fs, "", "fragcolor", NULL);
|
||||||
|
glGenVertexArrays( 1, (GLuint*)&vao );
|
||||||
|
}
|
||||||
|
|
||||||
|
glDisable(GL_BLEND);
|
||||||
|
|
||||||
|
handle old_shader = last_shader;
|
||||||
|
glUseProgram( program );
|
||||||
|
|
||||||
|
glViewport(0, 0, 512, 512);
|
||||||
|
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
|
glBindVertexArray( vao );
|
||||||
|
|
||||||
|
glDrawArrays( GL_TRIANGLES, 0, 6 );
|
||||||
|
profile_incstat("Render.num_drawcalls", +1);
|
||||||
|
profile_incstat("Render.num_triangles", +2);
|
||||||
|
|
||||||
|
glBindVertexArray( 0 );
|
||||||
|
|
||||||
|
glUseProgram( last_shader );
|
||||||
|
|
||||||
|
fbo_unbind();
|
||||||
|
fbo_destroy(lut_fbo);
|
||||||
}
|
}
|
||||||
|
|
||||||
texture_t brdf_lut() {
|
texture_t brdf_lut() {
|
||||||
|
@ -372649,7 +372692,7 @@ bool colormap( colormap_t *cm, const char *texture_name, bool load_as_srgb ) {
|
||||||
|
|
||||||
int srgb = load_as_srgb ? TEXTURE_SRGB : 0;
|
int srgb = load_as_srgb ? TEXTURE_SRGB : 0;
|
||||||
int hdr = strendi(texture_name, ".hdr") ? TEXTURE_FLOAT|TEXTURE_RGBA : 0;
|
int hdr = strendi(texture_name, ".hdr") ? TEXTURE_FLOAT|TEXTURE_RGBA : 0;
|
||||||
texture_t t = texture_compressed(texture_name, TEXTURE_LINEAR | TEXTURE_MIPMAPS | TEXTURE_REPEAT | hdr | srgb);
|
texture_t t = texture_compressed(texture_name, TEXTURE_LINEAR | TEXTURE_ANISOTROPY | TEXTURE_MIPMAPS | TEXTURE_REPEAT | hdr | srgb);
|
||||||
|
|
||||||
if( t.id == texture_checker().id ) {
|
if( t.id == texture_checker().id ) {
|
||||||
cm->texture = NULL;
|
cm->texture = NULL;
|
||||||
|
@ -373028,7 +373071,7 @@ void model_set_uniforms(model_t m, int shader, mat44 mv, mat44 proj, mat44 view,
|
||||||
shader_bool( "has_tex_skysphere", has_tex_skysphere );
|
shader_bool( "has_tex_skysphere", has_tex_skysphere );
|
||||||
shader_bool( "has_tex_skyenv", has_tex_skyenv );
|
shader_bool( "has_tex_skyenv", has_tex_skyenv );
|
||||||
if( has_tex_skysphere ) {
|
if( has_tex_skysphere ) {
|
||||||
float mipCount = floor( log2( m.sky_refl.h ) );
|
float mipCount = floor( log2( max(m.sky_refl.w, m.sky_refl.h) ) );
|
||||||
shader_texture("tex_skysphere", m.sky_refl);
|
shader_texture("tex_skysphere", m.sky_refl);
|
||||||
shader_float( "skysphere_mip_count", mipCount );
|
shader_float( "skysphere_mip_count", mipCount );
|
||||||
}
|
}
|
||||||
|
@ -382654,6 +382697,9 @@ static void v4k_post_init(float refresh_rate) {
|
||||||
|
|
||||||
hz = refresh_rate;
|
hz = refresh_rate;
|
||||||
// t = glfwGetTime();
|
// t = glfwGetTime();
|
||||||
|
|
||||||
|
// preload brdf LUT early
|
||||||
|
(void)brdf_lut();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
|
@ -48,6 +48,9 @@ static void v4k_post_init(float refresh_rate) {
|
||||||
|
|
||||||
hz = refresh_rate;
|
hz = refresh_rate;
|
||||||
// t = glfwGetTime();
|
// t = glfwGetTime();
|
||||||
|
|
||||||
|
// preload brdf LUT early
|
||||||
|
(void)brdf_lut();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
|
@ -1180,6 +1180,9 @@ texture_t texture_compressed_from_mem(const void *data, int len, unsigned flags)
|
||||||
if( dimensions > 0 ) glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
if( dimensions > 0 ) glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||||
if( dimensions > 1 ) glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
if( dimensions > 1 ) glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||||
if( dimensions > 2 ) glTexParameteri(target, GL_TEXTURE_WRAP_R, GL_REPEAT);
|
if( dimensions > 2 ) glTexParameteri(target, GL_TEXTURE_WRAP_R, GL_REPEAT);
|
||||||
|
if( flags&TEXTURE_CLAMP && dimensions > 0 ) glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
|
if( flags&TEXTURE_CLAMP && dimensions > 1 ) glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
|
if( flags&TEXTURE_CLAMP && dimensions > 2 ) glTexParameteri(target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
||||||
|
|
||||||
if( target == GL_TEXTURE_CUBE_MAP ) target = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
|
if( target == GL_TEXTURE_CUBE_MAP ) target = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
|
||||||
|
|
||||||
|
@ -2601,15 +2604,55 @@ int ui_fxs() {
|
||||||
static texture_t brdf = {0};
|
static texture_t brdf = {0};
|
||||||
|
|
||||||
static void brdf_load() {
|
static void brdf_load() {
|
||||||
const char *filename;
|
// generate texture
|
||||||
filename = "Skyboxes/brdf_lut1k_256x256_32F.ktx";
|
unsigned tex;
|
||||||
filename = "Skyboxes/brdf_lut2k_512x512_32F.ktx";
|
glGenTextures(1, &tex);
|
||||||
|
|
||||||
brdf = texture_compressed( filename,
|
glBindTexture(GL_TEXTURE_2D, tex);
|
||||||
TEXTURE_CLAMP | TEXTURE_NEAREST | TEXTURE_RG | TEXTURE_FLOAT
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RG16F, 512, 512, 0, GL_RG, GL_FLOAT, 0);
|
||||||
);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
unsigned texchecker = texture_checker().id;
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
ASSERT(brdf.id != texchecker, "!Couldn't load BRDF lookup table '%s'!", filename );
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
|
||||||
|
brdf.id = tex;
|
||||||
|
brdf.w = 512;
|
||||||
|
brdf.h = 512;
|
||||||
|
|
||||||
|
// create program and generate BRDF LUT
|
||||||
|
unsigned lut_fbo = fbo(tex, 0, 0), rbo=0;
|
||||||
|
fbo_bind(lut_fbo);
|
||||||
|
|
||||||
|
static int program = -1, vao = -1;
|
||||||
|
if( program < 0 ) {
|
||||||
|
const char* vs = vfs_read("shaders/vs_0_2_fullscreen_quad_B_flipped.glsl");
|
||||||
|
const char* fs = vfs_read("shaders/brdf.glsl");
|
||||||
|
|
||||||
|
program = shader(vs, fs, "", "fragcolor", NULL);
|
||||||
|
glGenVertexArrays( 1, (GLuint*)&vao );
|
||||||
|
}
|
||||||
|
|
||||||
|
glDisable(GL_BLEND);
|
||||||
|
|
||||||
|
handle old_shader = last_shader;
|
||||||
|
glUseProgram( program );
|
||||||
|
|
||||||
|
glViewport(0, 0, 512, 512);
|
||||||
|
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
|
glBindVertexArray( vao );
|
||||||
|
|
||||||
|
glDrawArrays( GL_TRIANGLES, 0, 6 );
|
||||||
|
profile_incstat("Render.num_drawcalls", +1);
|
||||||
|
profile_incstat("Render.num_triangles", +2);
|
||||||
|
|
||||||
|
glBindVertexArray( 0 );
|
||||||
|
|
||||||
|
glUseProgram( last_shader );
|
||||||
|
|
||||||
|
fbo_unbind();
|
||||||
|
fbo_destroy(lut_fbo);
|
||||||
}
|
}
|
||||||
|
|
||||||
texture_t brdf_lut() {
|
texture_t brdf_lut() {
|
||||||
|
@ -2630,7 +2673,7 @@ bool colormap( colormap_t *cm, const char *texture_name, bool load_as_srgb ) {
|
||||||
|
|
||||||
int srgb = load_as_srgb ? TEXTURE_SRGB : 0;
|
int srgb = load_as_srgb ? TEXTURE_SRGB : 0;
|
||||||
int hdr = strendi(texture_name, ".hdr") ? TEXTURE_FLOAT|TEXTURE_RGBA : 0;
|
int hdr = strendi(texture_name, ".hdr") ? TEXTURE_FLOAT|TEXTURE_RGBA : 0;
|
||||||
texture_t t = texture_compressed(texture_name, TEXTURE_LINEAR | TEXTURE_MIPMAPS | TEXTURE_REPEAT | hdr | srgb);
|
texture_t t = texture_compressed(texture_name, TEXTURE_LINEAR | TEXTURE_ANISOTROPY | TEXTURE_MIPMAPS | TEXTURE_REPEAT | hdr | srgb);
|
||||||
|
|
||||||
if( t.id == texture_checker().id ) {
|
if( t.id == texture_checker().id ) {
|
||||||
cm->texture = NULL;
|
cm->texture = NULL;
|
||||||
|
@ -3009,7 +3052,7 @@ void model_set_uniforms(model_t m, int shader, mat44 mv, mat44 proj, mat44 view,
|
||||||
shader_bool( "has_tex_skysphere", has_tex_skysphere );
|
shader_bool( "has_tex_skysphere", has_tex_skysphere );
|
||||||
shader_bool( "has_tex_skyenv", has_tex_skyenv );
|
shader_bool( "has_tex_skyenv", has_tex_skyenv );
|
||||||
if( has_tex_skysphere ) {
|
if( has_tex_skysphere ) {
|
||||||
float mipCount = floor( log2( m.sky_refl.h ) );
|
float mipCount = floor( log2( max(m.sky_refl.w, m.sky_refl.h) ) );
|
||||||
shader_texture("tex_skysphere", m.sky_refl);
|
shader_texture("tex_skysphere", m.sky_refl);
|
||||||
shader_float( "skysphere_mip_count", mipCount );
|
shader_float( "skysphere_mip_count", mipCount );
|
||||||
}
|
}
|
||||||
|
|
66
engine/v4k.c
66
engine/v4k.c
|
@ -18352,6 +18352,9 @@ texture_t texture_compressed_from_mem(const void *data, int len, unsigned flags)
|
||||||
if( dimensions > 0 ) glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
if( dimensions > 0 ) glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||||
if( dimensions > 1 ) glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
if( dimensions > 1 ) glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||||
if( dimensions > 2 ) glTexParameteri(target, GL_TEXTURE_WRAP_R, GL_REPEAT);
|
if( dimensions > 2 ) glTexParameteri(target, GL_TEXTURE_WRAP_R, GL_REPEAT);
|
||||||
|
if( flags&TEXTURE_CLAMP && dimensions > 0 ) glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
|
if( flags&TEXTURE_CLAMP && dimensions > 1 ) glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
|
if( flags&TEXTURE_CLAMP && dimensions > 2 ) glTexParameteri(target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
||||||
|
|
||||||
if( target == GL_TEXTURE_CUBE_MAP ) target = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
|
if( target == GL_TEXTURE_CUBE_MAP ) target = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
|
||||||
|
|
||||||
|
@ -19773,15 +19776,55 @@ int ui_fxs() {
|
||||||
static texture_t brdf = {0};
|
static texture_t brdf = {0};
|
||||||
|
|
||||||
static void brdf_load() {
|
static void brdf_load() {
|
||||||
const char *filename;
|
// generate texture
|
||||||
filename = "Skyboxes/brdf_lut1k_256x256_32F.ktx";
|
unsigned tex;
|
||||||
filename = "Skyboxes/brdf_lut2k_512x512_32F.ktx";
|
glGenTextures(1, &tex);
|
||||||
|
|
||||||
brdf = texture_compressed( filename,
|
glBindTexture(GL_TEXTURE_2D, tex);
|
||||||
TEXTURE_CLAMP | TEXTURE_NEAREST | TEXTURE_RG | TEXTURE_FLOAT
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RG16F, 512, 512, 0, GL_RG, GL_FLOAT, 0);
|
||||||
);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
unsigned texchecker = texture_checker().id;
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
ASSERT(brdf.id != texchecker, "!Couldn't load BRDF lookup table '%s'!", filename );
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
|
||||||
|
brdf.id = tex;
|
||||||
|
brdf.w = 512;
|
||||||
|
brdf.h = 512;
|
||||||
|
|
||||||
|
// create program and generate BRDF LUT
|
||||||
|
unsigned lut_fbo = fbo(tex, 0, 0), rbo=0;
|
||||||
|
fbo_bind(lut_fbo);
|
||||||
|
|
||||||
|
static int program = -1, vao = -1;
|
||||||
|
if( program < 0 ) {
|
||||||
|
const char* vs = vfs_read("shaders/vs_0_2_fullscreen_quad_B_flipped.glsl");
|
||||||
|
const char* fs = vfs_read("shaders/brdf.glsl");
|
||||||
|
|
||||||
|
program = shader(vs, fs, "", "fragcolor", NULL);
|
||||||
|
glGenVertexArrays( 1, (GLuint*)&vao );
|
||||||
|
}
|
||||||
|
|
||||||
|
glDisable(GL_BLEND);
|
||||||
|
|
||||||
|
handle old_shader = last_shader;
|
||||||
|
glUseProgram( program );
|
||||||
|
|
||||||
|
glViewport(0, 0, 512, 512);
|
||||||
|
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
|
glBindVertexArray( vao );
|
||||||
|
|
||||||
|
glDrawArrays( GL_TRIANGLES, 0, 6 );
|
||||||
|
profile_incstat("Render.num_drawcalls", +1);
|
||||||
|
profile_incstat("Render.num_triangles", +2);
|
||||||
|
|
||||||
|
glBindVertexArray( 0 );
|
||||||
|
|
||||||
|
glUseProgram( last_shader );
|
||||||
|
|
||||||
|
fbo_unbind();
|
||||||
|
fbo_destroy(lut_fbo);
|
||||||
}
|
}
|
||||||
|
|
||||||
texture_t brdf_lut() {
|
texture_t brdf_lut() {
|
||||||
|
@ -19802,7 +19845,7 @@ bool colormap( colormap_t *cm, const char *texture_name, bool load_as_srgb ) {
|
||||||
|
|
||||||
int srgb = load_as_srgb ? TEXTURE_SRGB : 0;
|
int srgb = load_as_srgb ? TEXTURE_SRGB : 0;
|
||||||
int hdr = strendi(texture_name, ".hdr") ? TEXTURE_FLOAT|TEXTURE_RGBA : 0;
|
int hdr = strendi(texture_name, ".hdr") ? TEXTURE_FLOAT|TEXTURE_RGBA : 0;
|
||||||
texture_t t = texture_compressed(texture_name, TEXTURE_LINEAR | TEXTURE_MIPMAPS | TEXTURE_REPEAT | hdr | srgb);
|
texture_t t = texture_compressed(texture_name, TEXTURE_LINEAR | TEXTURE_ANISOTROPY | TEXTURE_MIPMAPS | TEXTURE_REPEAT | hdr | srgb);
|
||||||
|
|
||||||
if( t.id == texture_checker().id ) {
|
if( t.id == texture_checker().id ) {
|
||||||
cm->texture = NULL;
|
cm->texture = NULL;
|
||||||
|
@ -20181,7 +20224,7 @@ void model_set_uniforms(model_t m, int shader, mat44 mv, mat44 proj, mat44 view,
|
||||||
shader_bool( "has_tex_skysphere", has_tex_skysphere );
|
shader_bool( "has_tex_skysphere", has_tex_skysphere );
|
||||||
shader_bool( "has_tex_skyenv", has_tex_skyenv );
|
shader_bool( "has_tex_skyenv", has_tex_skyenv );
|
||||||
if( has_tex_skysphere ) {
|
if( has_tex_skysphere ) {
|
||||||
float mipCount = floor( log2( m.sky_refl.h ) );
|
float mipCount = floor( log2( max(m.sky_refl.w, m.sky_refl.h) ) );
|
||||||
shader_texture("tex_skysphere", m.sky_refl);
|
shader_texture("tex_skysphere", m.sky_refl);
|
||||||
shader_float( "skysphere_mip_count", mipCount );
|
shader_float( "skysphere_mip_count", mipCount );
|
||||||
}
|
}
|
||||||
|
@ -29807,6 +29850,9 @@ static void v4k_post_init(float refresh_rate) {
|
||||||
|
|
||||||
hz = refresh_rate;
|
hz = refresh_rate;
|
||||||
// t = glfwGetTime();
|
// t = glfwGetTime();
|
||||||
|
|
||||||
|
// preload brdf LUT early
|
||||||
|
(void)brdf_lut();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
Loading…
Reference in New Issue