Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLukas Stockner <lukasstockner97>2022-09-16 16:04:47 +0300
committerJeroen Bakker <jeroen@blender.org>2022-09-16 16:10:09 +0300
commit44aaa9893ba876d23c7b9e93c2ed83c55f96afd9 (patch)
treead363a58c8a17efd5b916602a264d0fe2894e41c /source/blender/gpu
parent2eb19eeb19a77103d1f410004955cf17ca14abba (diff)
Eevee: Add support for Nishita sky texture
Sun Disc is currently not supported because it'll need special handling - on the one hand, I'm not sure if Eevee would handle a 1e6 coming out of a background shader without issues, and on the other hand it won't actually cast sharp shadows anyways. I guess we'd want to internally add a sun to the lamps if Sun Disc is enabled, but getting that right is tricky since the user could e.g. swap RGB channels in the node tree and the lamp wouldn't match that. Anyways, that can be handled later, the sky itself is already a start. Reviewed By: fclem Differential Revision: https://developer.blender.org/D13522
Diffstat (limited to 'source/blender/gpu')
-rw-r--r--source/blender/gpu/GPU_material.h7
-rw-r--r--source/blender/gpu/intern/gpu_codegen.cc4
-rw-r--r--source/blender/gpu/intern/gpu_material.c61
-rw-r--r--source/blender/gpu/intern/gpu_node_graph.c31
-rw-r--r--source/blender/gpu/intern/gpu_node_graph.h6
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_tex_sky.glsl44
6 files changed, 146 insertions, 7 deletions
diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h
index 023221543ec..922988bf95a 100644
--- a/source/blender/gpu/GPU_material.h
+++ b/source/blender/gpu/GPU_material.h
@@ -162,6 +162,12 @@ GPUNodeLink *GPU_image_tiled(GPUMaterial *mat,
struct ImageUser *iuser,
eGPUSamplerState sampler_state);
GPUNodeLink *GPU_image_tiled_mapping(GPUMaterial *mat, struct Image *ima, struct ImageUser *iuser);
+GPUNodeLink *GPU_image_sky(GPUMaterial *mat,
+ int width,
+ int height,
+ const float *pixels,
+ float *layer,
+ eGPUSamplerState sampler_state);
GPUNodeLink *GPU_color_band(GPUMaterial *mat, int size, float *pixels, float *row);
/**
@@ -297,6 +303,7 @@ typedef struct GPUMaterialTexture {
struct ImageUser iuser;
bool iuser_available;
struct GPUTexture **colorband;
+ struct GPUTexture **sky;
char sampler_name[32]; /* Name of sampler in GLSL. */
char tiled_mapping_name[32]; /* Name of tile mapping sampler in GLSL. */
int users;
diff --git a/source/blender/gpu/intern/gpu_codegen.cc b/source/blender/gpu/intern/gpu_codegen.cc
index 75e148e0a8f..2241bcf9f9b 100644
--- a/source/blender/gpu/intern/gpu_codegen.cc
+++ b/source/blender/gpu/intern/gpu_codegen.cc
@@ -386,6 +386,10 @@ void GPUCodegen::generate_resources()
const char *name = info.name_buffer.append_sampler_name(tex->sampler_name);
info.sampler(slot++, ImageType::FLOAT_1D_ARRAY, name, Frequency::BATCH);
}
+ else if (tex->sky) {
+ const char *name = info.name_buffer.append_sampler_name(tex->sampler_name);
+ info.sampler(0, ImageType::FLOAT_2D_ARRAY, name, Frequency::BATCH);
+ }
else if (tex->tiled_mapping_name[0] != '\0') {
const char *name = info.name_buffer.append_sampler_name(tex->sampler_name);
info.sampler(slot++, ImageType::FLOAT_2D_ARRAY, name, Frequency::BATCH);
diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c
index 75066b21e7b..96809db1587 100644
--- a/source/blender/gpu/intern/gpu_material.c
+++ b/source/blender/gpu/intern/gpu_material.c
@@ -41,12 +41,18 @@
/* Structs */
#define MAX_COLOR_BAND 128
+#define MAX_GPU_SKIES 8
typedef struct GPUColorBandBuilder {
float pixels[MAX_COLOR_BAND][CM_TABLE + 1][4];
int current_layer;
} GPUColorBandBuilder;
+typedef struct GPUSkyBuilder {
+ float pixels[MAX_GPU_SKIES][GPU_SKY_WIDTH * GPU_SKY_HEIGHT][4];
+ int current_layer;
+} GPUSkyBuilder;
+
struct GPUMaterial {
/* Contains GPUShader and source code for deferred compilation.
* Can be shared between similar material (i.e: sharing same nodetree topology). */
@@ -73,6 +79,10 @@ struct GPUMaterial {
GPUTexture *coba_tex;
/** Builder for coba_tex. */
GPUColorBandBuilder *coba_builder;
+ /** 2D Texture array containing all sky textures. */
+ GPUTexture *sky_tex;
+ /** Builder for sky_tex. */
+ GPUSkyBuilder *sky_builder;
/* Low level node graph(s). Also contains resources needed by the material. */
GPUNodeGraph graph;
@@ -98,6 +108,35 @@ struct GPUMaterial {
/* Functions */
+GPUTexture **gpu_material_sky_texture_layer_set(
+ GPUMaterial *mat, int width, int height, const float *pixels, float *row)
+{
+ /* In order to put all sky textures into one 2D array texture,
+ * we need them to be the same size. */
+ BLI_assert(width == GPU_SKY_WIDTH);
+ BLI_assert(height == GPU_SKY_HEIGHT);
+ UNUSED_VARS_NDEBUG(width, height);
+
+ if (mat->sky_builder == NULL) {
+ mat->sky_builder = MEM_mallocN(sizeof(GPUSkyBuilder), "GPUSkyBuilder");
+ mat->sky_builder->current_layer = 0;
+ }
+
+ int layer = mat->sky_builder->current_layer;
+ *row = (float)layer;
+
+ if (*row == MAX_GPU_SKIES) {
+ printf("Too many sky textures in shader!\n");
+ }
+ else {
+ float *dst = (float *)mat->sky_builder->pixels[layer];
+ memcpy(dst, pixels, sizeof(float) * GPU_SKY_WIDTH * GPU_SKY_HEIGHT * 4);
+ mat->sky_builder->current_layer += 1;
+ }
+
+ return &mat->sky_tex;
+}
+
GPUTexture **gpu_material_ramp_texture_row_set(GPUMaterial *mat,
int size,
float *pixels,
@@ -143,6 +182,24 @@ static void gpu_material_ramp_texture_build(GPUMaterial *mat)
mat->coba_builder = NULL;
}
+static void gpu_material_sky_texture_build(GPUMaterial *mat)
+{
+ if (mat->sky_builder == NULL) {
+ return;
+ }
+
+ mat->sky_tex = GPU_texture_create_2d_array("mat_sky",
+ GPU_SKY_WIDTH,
+ GPU_SKY_HEIGHT,
+ mat->sky_builder->current_layer,
+ 1,
+ GPU_RGBA32F,
+ (float *)mat->sky_builder->pixels);
+
+ MEM_freeN(mat->sky_builder);
+ mat->sky_builder = NULL;
+}
+
void GPU_material_free_single(GPUMaterial *material)
{
bool do_free = atomic_sub_and_fetch_uint32(&material->refcount, 1) == 0;
@@ -161,6 +218,9 @@ void GPU_material_free_single(GPUMaterial *material)
if (material->coba_tex != NULL) {
GPU_texture_free(material->coba_tex);
}
+ if (material->sky_tex != NULL) {
+ GPU_texture_free(material->sky_tex);
+ }
if (material->sss_profile != NULL) {
GPU_uniformbuf_free(material->sss_profile);
}
@@ -684,6 +744,7 @@ GPUMaterial *GPU_material_from_nodetree(Scene *scene,
ntreeGPUMaterialNodes(localtree, mat);
gpu_material_ramp_texture_build(mat);
+ gpu_material_sky_texture_build(mat);
{
/* Create source code and search pass cache for an already compiled version. */
diff --git a/source/blender/gpu/intern/gpu_node_graph.c b/source/blender/gpu/intern/gpu_node_graph.c
index f82af7538b5..a305413905b 100644
--- a/source/blender/gpu/intern/gpu_node_graph.c
+++ b/source/blender/gpu/intern/gpu_node_graph.c
@@ -112,6 +112,7 @@ static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, const eGPUType
break;
case GPU_NODE_LINK_IMAGE:
case GPU_NODE_LINK_IMAGE_TILED:
+ case GPU_NODE_LINK_IMAGE_SKY:
case GPU_NODE_LINK_COLORBAND:
input->source = GPU_SOURCE_TEX;
input->texture = link->texture;
@@ -438,6 +439,7 @@ static GPUMaterialTexture *gpu_node_graph_add_texture(GPUNodeGraph *graph,
Image *ima,
ImageUser *iuser,
struct GPUTexture **colorband,
+ struct GPUTexture **sky,
GPUNodeLinkType link_type,
eGPUSamplerState sampler_state)
{
@@ -445,7 +447,8 @@ static GPUMaterialTexture *gpu_node_graph_add_texture(GPUNodeGraph *graph,
int num_textures = 0;
GPUMaterialTexture *tex = graph->textures.first;
for (; tex; tex = tex->next) {
- if (tex->ima == ima && tex->colorband == colorband && tex->sampler_state == sampler_state) {
+ if (tex->ima == ima && tex->colorband == colorband && tex->sky == sky &&
+ tex->sampler_state == sampler_state) {
break;
}
num_textures++;
@@ -460,6 +463,7 @@ static GPUMaterialTexture *gpu_node_graph_add_texture(GPUNodeGraph *graph,
tex->iuser_available = true;
}
tex->colorband = colorband;
+ tex->sky = sky;
tex->sampler_state = sampler_state;
BLI_snprintf(tex->sampler_name, sizeof(tex->sampler_name), "samp%d", num_textures);
if (ELEM(link_type, GPU_NODE_LINK_IMAGE_TILED, GPU_NODE_LINK_IMAGE_TILED_MAPPING)) {
@@ -580,7 +584,24 @@ GPUNodeLink *GPU_image(GPUMaterial *mat,
GPUNodeLink *link = gpu_node_link_create();
link->link_type = GPU_NODE_LINK_IMAGE;
link->texture = gpu_node_graph_add_texture(
- graph, ima, iuser, NULL, link->link_type, sampler_state);
+ graph, ima, iuser, NULL, NULL, link->link_type, sampler_state);
+ return link;
+}
+
+GPUNodeLink *GPU_image_sky(GPUMaterial *mat,
+ int width,
+ int height,
+ const float *pixels,
+ float *layer,
+ eGPUSamplerState sampler_state)
+{
+ struct GPUTexture **sky = gpu_material_sky_texture_layer_set(mat, width, height, pixels, layer);
+
+ GPUNodeGraph *graph = gpu_material_node_graph(mat);
+ GPUNodeLink *link = gpu_node_link_create();
+ link->link_type = GPU_NODE_LINK_IMAGE_SKY;
+ link->texture = gpu_node_graph_add_texture(
+ graph, NULL, NULL, NULL, sky, link->link_type, sampler_state);
return link;
}
@@ -593,7 +614,7 @@ GPUNodeLink *GPU_image_tiled(GPUMaterial *mat,
GPUNodeLink *link = gpu_node_link_create();
link->link_type = GPU_NODE_LINK_IMAGE_TILED;
link->texture = gpu_node_graph_add_texture(
- graph, ima, iuser, NULL, link->link_type, sampler_state);
+ graph, ima, iuser, NULL, NULL, link->link_type, sampler_state);
return link;
}
@@ -603,7 +624,7 @@ GPUNodeLink *GPU_image_tiled_mapping(GPUMaterial *mat, Image *ima, ImageUser *iu
GPUNodeLink *link = gpu_node_link_create();
link->link_type = GPU_NODE_LINK_IMAGE_TILED_MAPPING;
link->texture = gpu_node_graph_add_texture(
- graph, ima, iuser, NULL, link->link_type, GPU_SAMPLER_MAX);
+ graph, ima, iuser, NULL, NULL, link->link_type, GPU_SAMPLER_MAX);
return link;
}
@@ -616,7 +637,7 @@ GPUNodeLink *GPU_color_band(GPUMaterial *mat, int size, float *pixels, float *ro
GPUNodeLink *link = gpu_node_link_create();
link->link_type = GPU_NODE_LINK_COLORBAND;
link->texture = gpu_node_graph_add_texture(
- graph, NULL, NULL, colorband, link->link_type, GPU_SAMPLER_MAX);
+ graph, NULL, NULL, colorband, NULL, link->link_type, GPU_SAMPLER_MAX);
return link;
}
diff --git a/source/blender/gpu/intern/gpu_node_graph.h b/source/blender/gpu/intern/gpu_node_graph.h
index 74afb721a1c..085620b30e4 100644
--- a/source/blender/gpu/intern/gpu_node_graph.h
+++ b/source/blender/gpu/intern/gpu_node_graph.h
@@ -47,6 +47,7 @@ typedef enum {
GPU_NODE_LINK_IMAGE,
GPU_NODE_LINK_IMAGE_TILED,
GPU_NODE_LINK_IMAGE_TILED_MAPPING,
+ GPU_NODE_LINK_IMAGE_SKY,
GPU_NODE_LINK_OUTPUT,
GPU_NODE_LINK_UNIFORM,
GPU_NODE_LINK_DIFFERENTIATE_FLOAT_FN,
@@ -197,6 +198,11 @@ struct GPUTexture **gpu_material_ramp_texture_row_set(struct GPUMaterial *mat,
int size,
float *pixels,
float *row);
+/**
+ * Returns the address of the future pointer to sky_tex
+ */
+struct GPUTexture **gpu_material_sky_texture_layer_set(
+ struct GPUMaterial *mat, int width, int height, const float *pixels, float *layer);
#ifdef __cplusplus
}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_tex_sky.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_tex_sky.glsl
index b6aad5904ff..c4b47bc1756 100644
--- a/source/blender/gpu/shaders/material/gpu_shader_material_tex_sky.glsl
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_tex_sky.glsl
@@ -144,7 +144,47 @@ void node_tex_sky_hosekwilkie(vec3 co,
color = vec4(dot(xyz_to_r, xyz), dot(xyz_to_g, xyz), dot(xyz_to_b, xyz), 1);
}
-void node_tex_sky_nishita(vec3 co, out vec4 color)
+void node_tex_sky_nishita(vec3 co,
+ float sun_rotation,
+ vec3 xyz_to_r,
+ vec3 xyz_to_g,
+ vec3 xyz_to_b,
+ sampler2DArray ima,
+ float layer,
+ out vec4 color)
{
- color = vec4(1.0);
+ vec3 spherical = sky_spherical_coordinates(co);
+
+ vec3 xyz;
+ if (co.z < -0.4) {
+ /* too far below the horizon, just return black */
+ color = vec4(0, 0, 0, 1);
+ }
+ else {
+ /* evaluate longitudinal position on the map */
+ float x = (spherical.y + M_PI + sun_rotation) / M_2PI;
+ if (x > 1.0) {
+ x -= 1.0;
+ }
+
+ float fade;
+ float y;
+ if (co.z < 0.0) {
+ /* we're below the horizon, so extend the map by blending from values at the horizon
+ * to zero according to a cubic falloff */
+ fade = 1.0 + co.z * 2.5;
+ fade = fade * fade * fade;
+ y = 0.0;
+ }
+ else {
+ /* we're above the horizon, so compute the lateral position by inverting the remapped
+ * coordinates that are preserve to have more detail near the horizon. */
+ fade = 1.0;
+ y = sqrt((M_PI_2 - spherical.x) / M_PI_2);
+ }
+
+ /* look up color in the precomputed map and convert to RGB */
+ xyz = fade * texture(ima, vec3(x, y, layer)).rgb;
+ color = vec4(dot(xyz_to_r, xyz), dot(xyz_to_g, xyz), dot(xyz_to_b, xyz), 1);
+ }
}