Merge pull request #559 from w23/bluenoise
vk: textures: add blue noise textures
This commit is contained in:
commit
e04a19a0af
|
@ -399,6 +399,19 @@ TODO: can we not have a BLAS/model for each submodel? Can it be per-model instea
|
|||
- ~~R_DrawStudioModel is the main func for drawing studio model. Called from scene code for each studio entity, with everything current (RI and stuff) set up~~
|
||||
- `R_StudioDrawModelInternal()` is the main one. It is where it splits into renderer-vs-game rendering functions.
|
||||
|
||||
# 2023-09-11 E293
|
||||
- light shaders include structure
|
||||
- ray_light_direct_{poly,point}.comp
|
||||
- ray_light_direct.glsl
|
||||
- utils.glsl
|
||||
- noise.glsl
|
||||
- ray_interop.h
|
||||
- ray_kusochki.glsl
|
||||
- light.glsl
|
||||
- brdf.h
|
||||
- light_common.glsl
|
||||
- LIGHT_POLYGON: light_polygon.glsl
|
||||
|
||||
# 2023-09-19 E298
|
||||
## SURF_DRAWSKY
|
||||
- (context: want to remove kXVkMaterialSky, #474)
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
// *Really* minimal PCG32 code / (c) 2014 M.E. O'Neill / pcg-random.org
|
||||
// Licensed under Apache License 2.0 (NO WARRANTY, etc. see website)
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct { uint64_t state; uint64_t inc; } pcg32_random_t;
|
||||
|
||||
uint32_t pcg32_random_r(pcg32_random_t* rng);
|
||||
|
||||
#if defined(PCG_IMPLEMENT)
|
||||
uint32_t pcg32_random_r(pcg32_random_t* rng)
|
||||
{
|
||||
uint64_t oldstate = rng->state;
|
||||
// Advance internal state
|
||||
rng->state = oldstate * 6364136223846793005ULL + (rng->inc|1);
|
||||
// Calculate output function (XSH RR), uses old state for max ILP
|
||||
uint32_t xorshifted = ((oldstate >> 18u) ^ oldstate) >> 27u;
|
||||
uint32_t rot = oldstate >> 59u;
|
||||
return (xorshifted >> rot) | (xorshifted << ((-rot) & 31));
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,20 @@
|
|||
#ifndef BLUENOISE_H_INCLUDED
|
||||
#define BLUENOISE_H_INCLUDED
|
||||
|
||||
// Depends on uniform sampler2D textures[MAX_TEXTURES] binding being defined
|
||||
|
||||
// This is the same hardcoded value as in vk_textures.h
|
||||
// Please keep them in sync onegai uwu
|
||||
// TODO:
|
||||
// - make bluenoise texture a separate binding, not part of textures[] array
|
||||
// - make it a 3D texture
|
||||
#define BLUE_NOISE_TEXTURE_BEGIN 6
|
||||
|
||||
// Also see vk_textures.h, keep in sync, etc etc
|
||||
#define BLUE_NOISE_SIZE 64
|
||||
vec4 blueNoise(ivec3 v) {
|
||||
v %= BLUE_NOISE_SIZE;
|
||||
return texelFetch(textures[BLUE_NOISE_TEXTURE_BEGIN+v.z], v.xy, 0);
|
||||
}
|
||||
|
||||
#endif // ifndef BLUENOISE_H_INCLUDED
|
|
@ -36,6 +36,10 @@ layout(set = 0, binding = 15, rgba16f) uniform image2D prev_temporal_diffuse;
|
|||
layout(set = 0, binding = 16, rgba16f) uniform image2D out_temporal_specular;
|
||||
layout(set = 0, binding = 17, rgba16f) uniform image2D prev_temporal_specular;
|
||||
|
||||
#ifdef DEBUG_NOISE
|
||||
layout(set = 0, binding = 18) uniform sampler2D textures[MAX_TEXTURES];
|
||||
include "bluenoise.glsl"
|
||||
#endif
|
||||
|
||||
const int INDIRECT_SCALE = 2;
|
||||
|
||||
|
@ -185,6 +189,10 @@ void main() {
|
|||
return;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_NOISE
|
||||
imageStore(out_dest, pix, blueNoise(ivec3(pix.xy, ubo.ubo.frame_counter))); return;
|
||||
#endif
|
||||
|
||||
/* if (pix.y < res.y / 3) { */
|
||||
/* imageStore(out_dest, pix, vec4(pow(float(pix.x) / res.x, 2.2))); return; */
|
||||
/* } else if (pix.y < res.y * 2 / 3) { */
|
||||
|
|
|
@ -173,7 +173,8 @@ struct UniformBuffer {
|
|||
mat4 prev_inv_proj, prev_inv_view;
|
||||
float ray_cone_width;
|
||||
uint random_seed;
|
||||
PAD(2)
|
||||
uint frame_counter;
|
||||
PAD(1)
|
||||
};
|
||||
|
||||
#undef PAD
|
||||
|
|
|
@ -140,7 +140,7 @@ void VK_RayFrameBegin( void ) {
|
|||
RT_LightsFrameBegin();
|
||||
}
|
||||
|
||||
static void prepareUniformBuffer( const vk_ray_frame_render_args_t *args, int frame_index, float fov_angle_y ) {
|
||||
static void prepareUniformBuffer( const vk_ray_frame_render_args_t *args, int frame_index, uint32_t frame_counter, float fov_angle_y ) {
|
||||
struct UniformBuffer *ubo = (struct UniformBuffer*)((char*)g_rtx.uniform_buffer.mapped + frame_index * g_rtx.uniform_unit_size);
|
||||
|
||||
matrix4x4 proj_inv, view_inv;
|
||||
|
@ -160,11 +160,13 @@ static void prepareUniformBuffer( const vk_ray_frame_render_args_t *args, int fr
|
|||
|
||||
ubo->ray_cone_width = atanf((2.0f*tanf(DEG2RAD(fov_angle_y) * 0.5f)) / (float)FRAME_HEIGHT);
|
||||
ubo->random_seed = (uint32_t)gEngine.COM_RandomLong(0, INT32_MAX);
|
||||
ubo->frame_counter = frame_counter;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
const vk_ray_frame_render_args_t* render_args;
|
||||
int frame_index;
|
||||
uint32_t frame_counter;
|
||||
float fov_angle_y;
|
||||
const vk_lights_bindings_t *light_bindings;
|
||||
} perform_tracing_args_t;
|
||||
|
@ -271,7 +273,7 @@ static void performTracing( vk_combuf_t *combuf, const perform_tracing_args_t* a
|
|||
// TODO move this to "TLAS producer"
|
||||
g_rtx.res[ExternalResource_tlas].resource = RT_VkAccelPrepareTlas(combuf);
|
||||
|
||||
prepareUniformBuffer(args->render_args, args->frame_index, args->fov_angle_y);
|
||||
prepareUniformBuffer(args->render_args, args->frame_index, args->frame_counter, args->fov_angle_y);
|
||||
|
||||
{ // FIXME this should be done automatically inside meatpipe, TODO
|
||||
//const uint32_t size = sizeof(struct Lights);
|
||||
|
@ -571,6 +573,7 @@ void VK_RayFrameEnd(const vk_ray_frame_render_args_t* args)
|
|||
const perform_tracing_args_t trace_args = {
|
||||
.render_args = args,
|
||||
.frame_index = (g_rtx.frame_number % 2),
|
||||
.frame_counter = g_rtx.frame_number,
|
||||
.fov_angle_y = args->fov_angle_y,
|
||||
.light_bindings = &light_bindings,
|
||||
};
|
||||
|
|
|
@ -15,6 +15,9 @@
|
|||
#include "com_strings.h"
|
||||
#include "eiface.h"
|
||||
|
||||
#define PCG_IMPLEMENT
|
||||
#include "pcg.h"
|
||||
|
||||
#include <memory.h>
|
||||
#include <math.h>
|
||||
|
||||
|
@ -262,6 +265,84 @@ static void VK_ProcessImage( vk_texture_t *tex, rgbdata_t *pic )
|
|||
|
||||
static qboolean uploadTexture(vk_texture_t *tex, rgbdata_t *const *const layers, int num_layers, qboolean cubemap);
|
||||
|
||||
static int VK_LoadTextureF(int flags, const char *fmt, ...) {
|
||||
int tex_id = 0;
|
||||
char buffer[1024];
|
||||
va_list argptr;
|
||||
va_start( argptr, fmt );
|
||||
vsnprintf( buffer, sizeof buffer, fmt, argptr );
|
||||
va_end( argptr );
|
||||
|
||||
return VK_LoadTexture(buffer, NULL, 0, flags);
|
||||
}
|
||||
|
||||
#define BLUE_NOISE_NAME_F "bluenoise/LDR_RGBA_%d.png"
|
||||
|
||||
static qboolean generateFallbackNoiseTextures(void) {
|
||||
pcg32_random_t pcg_state = {
|
||||
BLUE_NOISE_SIZE * BLUE_NOISE_SIZE - 1,
|
||||
17,
|
||||
};
|
||||
uint32_t scratch[BLUE_NOISE_SIZE * BLUE_NOISE_SIZE];
|
||||
rgbdata_t pic = {
|
||||
.width = BLUE_NOISE_SIZE,
|
||||
.height = BLUE_NOISE_SIZE,
|
||||
.depth = 1,
|
||||
.flags = 0,
|
||||
.type = PF_RGBA_32,
|
||||
.size = BLUE_NOISE_SIZE * BLUE_NOISE_SIZE * 4,
|
||||
.buffer = (byte*)&scratch,
|
||||
.palette = NULL,
|
||||
.numMips = 1,
|
||||
.encode = 0,
|
||||
};
|
||||
|
||||
int blueNoiseTexturesBegin = -1;
|
||||
for (int i = 0; i < BLUE_NOISE_SIZE; ++i) {
|
||||
for (int j = 0; j < COUNTOF(scratch); ++j) {
|
||||
scratch[j] = pcg32_random_r(&pcg_state);
|
||||
}
|
||||
|
||||
char name[256];
|
||||
snprintf(name, sizeof(name), BLUE_NOISE_NAME_F, i);
|
||||
const int texid = VK_LoadTextureInternal(name, &pic, TF_NOMIPMAP);
|
||||
ASSERT(texid > 0);
|
||||
|
||||
if (blueNoiseTexturesBegin == -1) {
|
||||
ASSERT(texid == BLUE_NOISE_TEXTURE_ID);
|
||||
blueNoiseTexturesBegin = texid;
|
||||
} else {
|
||||
ASSERT(blueNoiseTexturesBegin + i == texid);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static qboolean loadBlueNoiseTextures(void) {
|
||||
int blueNoiseTexturesBegin = -1;
|
||||
for (int i = 0; i < 64; ++i) {
|
||||
const int texid = VK_LoadTextureF(TF_NOMIPMAP, BLUE_NOISE_NAME_F, i);
|
||||
|
||||
if (blueNoiseTexturesBegin == -1) {
|
||||
if (texid <= 0) {
|
||||
ERR("Couldn't find precomputed blue noise textures. Generating bad quality regular noise textures as a fallback");
|
||||
return generateFallbackNoiseTextures();
|
||||
}
|
||||
|
||||
blueNoiseTexturesBegin = texid;
|
||||
} else {
|
||||
ASSERT(texid > 0);
|
||||
ASSERT(blueNoiseTexturesBegin + i == texid);
|
||||
}
|
||||
}
|
||||
|
||||
INFO("Base blue noise texture is %d", blueNoiseTexturesBegin);
|
||||
ASSERT(blueNoiseTexturesBegin == BLUE_NOISE_TEXTURE_ID);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void VK_CreateInternalTextures( void )
|
||||
{
|
||||
int dx2, dy, d;
|
||||
|
@ -338,6 +419,8 @@ static void VK_CreateInternalTextures( void )
|
|||
|
||||
uploadTexture( &tglob.cubemap_placeholder, sides, 6, true );
|
||||
}
|
||||
|
||||
loadBlueNoiseTextures();
|
||||
}
|
||||
|
||||
static VkFormat VK_GetFormat(pixformat_t format) {
|
||||
|
|
|
@ -41,6 +41,14 @@ typedef struct vk_textures_global_s
|
|||
int dlightTexture; // custom dlight texture
|
||||
int cinTexture; // cinematic texture
|
||||
|
||||
// Hardcoded expected blue noise texture slot
|
||||
// TODO consider moving it into a separate resource bindable by request
|
||||
// TODO make it a 3D texture. Currently it's just a sequence of BLUE_NOISE_SIZE textures, loaded into consecutive slots.
|
||||
#define BLUE_NOISE_TEXTURE_ID 6
|
||||
|
||||
// Hardcode blue noise texture size to 64x64x64
|
||||
#define BLUE_NOISE_SIZE 64
|
||||
|
||||
qboolean fCustomSkybox; // TODO do we need this for anything?
|
||||
|
||||
vk_texture_t skybox_cube;
|
||||
|
|
Loading…
Reference in New Issue