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:
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);
+ }
}