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/draw/engines/clay/clay_engine.c')
-rw-r--r--source/blender/draw/engines/clay/clay_engine.c985
1 files changed, 0 insertions, 985 deletions
diff --git a/source/blender/draw/engines/clay/clay_engine.c b/source/blender/draw/engines/clay/clay_engine.c
deleted file mode 100644
index 5d3717097b1..00000000000
--- a/source/blender/draw/engines/clay/clay_engine.c
+++ /dev/null
@@ -1,985 +0,0 @@
-/*
- * Copyright 2016, Blender Foundation.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Contributor(s): Blender Institute
- *
- */
-
-#include "BLI_utildefines.h"
-#include "BLI_string_utils.h"
-#include "BLI_rand.h"
-
-#include "DNA_particle_types.h"
-#include "DNA_view3d_types.h"
-
-#include "BKE_icons.h"
-#include "BKE_idprop.h"
-#include "BKE_main.h"
-#include "BKE_particle.h"
-
-#include "GPU_shader.h"
-
-#include "IMB_imbuf.h"
-#include "IMB_imbuf_types.h"
-
-#include "UI_resources.h"
-#include "UI_interface_icons.h"
-
-#include "DRW_render.h"
-
-#include "DEG_depsgraph_query.h"
-
-#include "clay_engine.h"
-
-#ifdef WITH_CLAY_ENGINE
-#include "../eevee/eevee_lut.h" /* TODO find somewhere to share blue noise Table */
-
-/* Shaders */
-
-#define CLAY_ENGINE "BLENDER_CLAY"
-
-#define MAX_CLAY_MAT 512 /* 512 = 9 bit material id */
-
-#define SHADER_DEFINES_NO_AO \
- "#define MAX_MATERIAL " STRINGIFY(MAX_CLAY_MAT) "\n" \
- "#define USE_ROTATION\n" \
- "#define USE_HSV\n"
-
-#define SHADER_DEFINES \
- SHADER_DEFINES_NO_AO \
- "#define USE_AO\n"
-
-extern char datatoc_clay_frag_glsl[];
-extern char datatoc_clay_prepass_frag_glsl[];
-extern char datatoc_clay_copy_glsl[];
-extern char datatoc_clay_vert_glsl[];
-extern char datatoc_clay_fxaa_glsl[];
-extern char datatoc_clay_particle_vert_glsl[];
-extern char datatoc_clay_particle_strand_frag_glsl[];
-extern char datatoc_ssao_alchemy_glsl[];
-extern char datatoc_common_fxaa_lib_glsl[];
-
-/* *********** LISTS *********** */
-
-/**
- * UBOs data needs to be 16 byte aligned (size of vec4)
- *
- * Reminder: float, int, bool are 4 bytes
- *
- * \note struct is expected to be initialized with all pad-bits zero'd
- * so we can use 'memcmp' to check for duplicates. Possibly hash data later.
- */
-typedef struct CLAY_UBO_Material {
- float ssao_params_var[4];
- /* - 16 -*/
- float matcap_hsv[3];
- float matcap_id; /* even float encoding have enough precision */
- /* - 16 -*/
- float matcap_rot[2];
- float pad[2]; /* ensure 16 bytes alignement */
-} CLAY_UBO_Material; /* 48 bytes */
-BLI_STATIC_ASSERT_ALIGN(CLAY_UBO_Material, 16)
-
-typedef struct CLAY_HAIR_UBO_Material {
- float hair_randomness;
- float matcap_id;
- float matcap_rot[2];
- float matcap_hsv[3];
- float pad;
-} CLAY_HAIR_UBO_Material; /* 32 bytes */
-BLI_STATIC_ASSERT_ALIGN(CLAY_HAIR_UBO_Material, 16)
-
-typedef struct CLAY_UBO_Storage {
- CLAY_UBO_Material materials[MAX_CLAY_MAT];
-} CLAY_UBO_Storage;
-
-typedef struct CLAY_HAIR_UBO_Storage {
- CLAY_HAIR_UBO_Material materials[MAX_CLAY_MAT];
-} CLAY_HAIR_UBO_Storage;
-
-/* GPUViewport.storage
- * Is freed everytime the viewport engine changes */
-typedef struct CLAY_Storage {
- /* Materials Parameter UBO */
- CLAY_UBO_Storage mat_storage;
- CLAY_HAIR_UBO_Storage hair_mat_storage;
- int ubo_current_id;
- int hair_ubo_current_id;
- DRWShadingGroup *shgrps[MAX_CLAY_MAT];
- DRWShadingGroup *shgrps_flat[MAX_CLAY_MAT];
- DRWShadingGroup *shgrps_pre[MAX_CLAY_MAT];
- DRWShadingGroup *shgrps_pre_flat[MAX_CLAY_MAT];
- DRWShadingGroup *hair_shgrps[MAX_CLAY_MAT];
-} CLAY_Storage;
-
-typedef struct CLAY_StorageList {
- struct CLAY_Storage *storage;
- struct CLAY_PrivateData *g_data;
-} CLAY_StorageList;
-
-typedef struct CLAY_FramebufferList {
- struct GPUFrameBuffer *antialias_fb;
- struct GPUFrameBuffer *prepass_fb;
-} CLAY_FramebufferList;
-
-typedef struct CLAY_PassList {
- struct DRWPass *clay_ps;
- struct DRWPass *clay_cull_ps;
- struct DRWPass *clay_flat_ps;
- struct DRWPass *clay_flat_cull_ps;
- struct DRWPass *clay_pre_ps;
- struct DRWPass *clay_pre_cull_ps;
- struct DRWPass *clay_flat_pre_ps;
- struct DRWPass *clay_flat_pre_cull_ps;
- struct DRWPass *clay_deferred_ps;
- struct DRWPass *fxaa_ps;
- struct DRWPass *copy_ps;
- struct DRWPass *hair_pass;
-} CLAY_PassList;
-
-
-typedef struct CLAY_Data {
- void *engine_type;
- CLAY_FramebufferList *fbl;
- DRWViewportEmptyList *txl;
- CLAY_PassList *psl;
- CLAY_StorageList *stl;
-} CLAY_Data;
-
-typedef struct CLAY_ViewLayerData {
- struct GPUTexture *jitter_tx;
- struct GPUUniformBuffer *mat_ubo;
- struct GPUUniformBuffer *matcaps_ubo;
- struct GPUUniformBuffer *hair_mat_ubo;
- struct GPUUniformBuffer *sampling_ubo;
- int cached_sample_num;
-} CLAY_ViewLayerData;
-
-/* *********** STATIC *********** */
-
-static struct {
- /* Shading Pass */
- struct GPUShader *clay_sh;
- struct GPUShader *clay_flat_sh;
- struct GPUShader *clay_prepass_flat_sh;
- struct GPUShader *clay_prepass_sh;
- struct GPUShader *clay_deferred_shading_sh;
- struct GPUShader *fxaa_sh;
- struct GPUShader *copy_sh;
- struct GPUShader *hair_sh;
- /* Matcap textures */
- struct GPUTexture *matcap_array;
- float matcap_colors[24][4];
- /* Just a serie of int from 0 to MAX_CLAY_MAT-1 */
- int ubo_mat_idxs[MAX_CLAY_MAT];
- /* To avoid useless texture and ubo binds. */
- bool first_shgrp;
-} e_data = {NULL}; /* Engine data */
-
-typedef struct CLAY_PrivateData {
- DRWShadingGroup *depth_shgrp;
- DRWShadingGroup *depth_shgrp_select;
- DRWShadingGroup *depth_shgrp_active;
- DRWShadingGroup *depth_shgrp_cull;
- DRWShadingGroup *depth_shgrp_cull_select;
- DRWShadingGroup *depth_shgrp_cull_active;
- /* Deferred shading */
- struct GPUTexture *depth_tx; /* ref only, not alloced */
- struct GPUTexture *normal_tx; /* ref only, not alloced */
- struct GPUTexture *id_tx; /* ref only, not alloced */
- struct GPUTexture *color_copy; /* ref only, not alloced */
- bool enable_deferred_path;
- /* Ssao */
- float winmat[4][4];
- float viewvecs[3][4];
- float ssao_params[4];
-} CLAY_PrivateData; /* Transient data */
-
-/* Functions */
-
-static void clay_view_layer_data_free(void *storage)
-{
- CLAY_ViewLayerData *sldata = (CLAY_ViewLayerData *)storage;
-
- DRW_UBO_FREE_SAFE(sldata->mat_ubo);
- DRW_UBO_FREE_SAFE(sldata->matcaps_ubo);
- DRW_UBO_FREE_SAFE(sldata->hair_mat_ubo);
- DRW_UBO_FREE_SAFE(sldata->sampling_ubo);
- DRW_TEXTURE_FREE_SAFE(sldata->jitter_tx);
-}
-
-static CLAY_ViewLayerData *CLAY_view_layer_data_get(void)
-{
- CLAY_ViewLayerData **sldata = (CLAY_ViewLayerData **)DRW_view_layer_engine_data_ensure(
- &draw_engine_clay_type, &clay_view_layer_data_free);
-
- if (*sldata == NULL) {
- *sldata = MEM_callocN(sizeof(**sldata), "CLAY_ViewLayerData");
- }
-
- return *sldata;
-}
-
-static void add_icon_to_rect(PreviewImage *prv, float *final_rect, int layer)
-{
- int image_size = prv->w[0] * prv->h[0];
- float *new_rect = &final_rect[image_size * 4 * layer];
-
- IMB_buffer_float_from_byte(new_rect, (unsigned char *)prv->rect[0], IB_PROFILE_SRGB, IB_PROFILE_SRGB,
- false, prv->w[0], prv->h[0], prv->w[0], prv->w[0]);
-
- /* Find overall color */
- for (int y = 0; y < 4; ++y) {
- for (int x = 0; x < 4; ++x) {
- e_data.matcap_colors[layer][0] += new_rect[y * 512 * 128 * 4 + x * 128 * 4 + 0];
- e_data.matcap_colors[layer][1] += new_rect[y * 512 * 128 * 4 + x * 128 * 4 + 1];
- e_data.matcap_colors[layer][2] += new_rect[y * 512 * 128 * 4 + x * 128 * 4 + 2];
- }
- }
-
- e_data.matcap_colors[layer][0] /= 16.0f * 2.0f; /* the * 2 is to darken for shadows */
- e_data.matcap_colors[layer][1] /= 16.0f * 2.0f;
- e_data.matcap_colors[layer][2] /= 16.0f * 2.0f;
-}
-
-static struct GPUTexture *load_matcaps(PreviewImage *prv[24], int nbr)
-{
- struct GPUTexture *tex;
- int w = prv[0]->w[0];
- int h = prv[0]->h[0];
- float *final_rect = MEM_callocN(sizeof(float) * 4 * w * h * nbr, "Clay Matcap array rect");
-
- for (int i = 0; i < nbr; ++i) {
- add_icon_to_rect(prv[i], final_rect, i);
- BKE_previewimg_free(&prv[i]);
- }
-
- tex = DRW_texture_create_2D_array(w, h, nbr, GPU_RGBA8, DRW_TEX_FILTER, final_rect);
- MEM_freeN(final_rect);
-
- return tex;
-}
-
-static int matcap_to_index(int matcap)
-{
- return matcap - 1;
-}
-
-/* Using Hammersley distribution */
-static float *create_disk_samples(int num_samples)
-{
- /* vec4 to ensure memory alignment. */
- float (*texels)[4] = MEM_mallocN(sizeof(float[4]) * num_samples, "concentric_tex");
- const float num_samples_inv = 1.0f / num_samples;
-
- for (int i = 0; i < num_samples; i++) {
- float r = (i + 0.5f) * num_samples_inv;
- double dphi;
- BLI_hammersley_1D(i, &dphi);
-
- float phi = (float)dphi * 2.0f * M_PI;
- texels[i][0] = cosf(phi);
- texels[i][1] = sinf(phi);
- /* This deliberatly distribute more samples
- * at the center of the disk (and thus the shadow). */
- texels[i][2] = r;
- }
-
- return (float *)texels;
-}
-
-static struct GPUTexture *create_jitter_texture(int num_samples)
-{
- float jitter[64 * 64][3];
- const float num_samples_inv = 1.0f / num_samples;
-
- for (int i = 0; i < 64 * 64; i++) {
- float phi = blue_noise[i][0] * 2.0f * M_PI;
- /* This rotate the sample per pixels */
- jitter[i][0] = cosf(phi);
- jitter[i][1] = sinf(phi);
- /* This offset the sample along it's direction axis (reduce banding) */
- float bn = blue_noise[i][1] - 0.5f;
- CLAMP(bn, -0.499f, 0.499f); /* fix fireflies */
- jitter[i][2] = bn * num_samples_inv;
- }
-
- UNUSED_VARS(bsdf_split_sum_ggx, btdf_split_sum_ggx, ltc_mag_ggx, ltc_mat_ggx, ltc_disk_integral);
-
- return DRW_texture_create_2D(64, 64, GPU_RGB16F, DRW_TEX_FILTER | DRW_TEX_WRAP, &jitter[0][0]);
-}
-
-static void clay_engine_init(void *vedata)
-{
- CLAY_StorageList *stl = ((CLAY_Data *)vedata)->stl;
- CLAY_FramebufferList *fbl = ((CLAY_Data *)vedata)->fbl;
- CLAY_ViewLayerData *sldata = CLAY_view_layer_data_get();
- DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
-
- /* Create Texture Array */
- if (!e_data.matcap_array) {
- PreviewImage *prv[24]; /* For now use all of the 24 internal matcaps */
- const int num_matcap = ARRAY_SIZE(prv);
-
- /* TODO only load used matcaps */
- for (int i = 0; i < num_matcap; ++i) {
- prv[i] = UI_icon_to_preview((int)ICON_MATCAP_01 + i);
- }
-
- e_data.matcap_array = load_matcaps(prv, num_matcap);
- }
-
- /* Shading pass */
- if (!e_data.clay_sh) {
- char *matcap_with_ao = BLI_string_joinN(
- datatoc_clay_frag_glsl,
- datatoc_ssao_alchemy_glsl);
-
- e_data.clay_sh = DRW_shader_create(
- datatoc_clay_vert_glsl, NULL, datatoc_clay_frag_glsl,
- SHADER_DEFINES_NO_AO);
- e_data.clay_flat_sh = DRW_shader_create(
- datatoc_clay_vert_glsl, NULL, datatoc_clay_frag_glsl,
- SHADER_DEFINES_NO_AO
- "#define USE_FLAT_NORMAL\n");
-
- e_data.clay_prepass_sh = DRW_shader_create(
- datatoc_clay_vert_glsl, NULL, datatoc_clay_prepass_frag_glsl,
- SHADER_DEFINES);
- e_data.clay_prepass_flat_sh = DRW_shader_create(
- datatoc_clay_vert_glsl, NULL, datatoc_clay_prepass_frag_glsl,
- SHADER_DEFINES
- "#define USE_FLAT_NORMAL\n");
-
- e_data.clay_deferred_shading_sh = DRW_shader_create_fullscreen(
- matcap_with_ao,
- SHADER_DEFINES
- "#define DEFERRED_SHADING\n");
-
- MEM_freeN(matcap_with_ao);
-
- char *fxaa_str = BLI_string_joinN(
- datatoc_common_fxaa_lib_glsl,
- datatoc_clay_fxaa_glsl);
-
- e_data.fxaa_sh = DRW_shader_create_fullscreen(fxaa_str, NULL);
-
- MEM_freeN(fxaa_str);
-
- e_data.copy_sh = DRW_shader_create_fullscreen(datatoc_clay_copy_glsl, NULL);
- }
-
- if (!stl->storage) {
- stl->storage = MEM_callocN(sizeof(CLAY_Storage), "CLAY_Storage");
- }
-
- if (!stl->g_data) {
- stl->g_data = MEM_mallocN(sizeof(*stl->g_data), "CLAY_PrivateStorage");
- }
-
- CLAY_PrivateData *g_data = stl->g_data;
-
- if (!sldata->mat_ubo) {
- sldata->mat_ubo = DRW_uniformbuffer_create(sizeof(CLAY_UBO_Storage), NULL);
- }
-
- if (!sldata->hair_mat_ubo) {
- sldata->hair_mat_ubo = DRW_uniformbuffer_create(sizeof(CLAY_HAIR_UBO_Storage), NULL);
- }
-
- if (!sldata->matcaps_ubo) {
- sldata->matcaps_ubo = DRW_uniformbuffer_create(sizeof(e_data.matcap_colors), e_data.matcap_colors);
- }
-
- if (e_data.ubo_mat_idxs[1] == 0) {
- /* Just int to have pointers to them */
- for (int i = 0; i < MAX_CLAY_MAT; ++i) {
- e_data.ubo_mat_idxs[i] = i;
- }
- }
-
- /* FBO setup */
- {
- const float *viewport_size = DRW_viewport_size_get();
- const int size[2] = {(int)viewport_size[0], (int)viewport_size[1]};
-
- g_data->normal_tx = DRW_texture_pool_query_2D(size[0], size[1], GPU_RG8, &draw_engine_clay_type);
- g_data->id_tx = DRW_texture_pool_query_2D(size[0], size[1], GPU_R16UI, &draw_engine_clay_type);
-
- GPU_framebuffer_ensure_config(&fbl->prepass_fb, {
- GPU_ATTACHMENT_TEXTURE(dtxl->depth),
- GPU_ATTACHMENT_TEXTURE(g_data->normal_tx),
- GPU_ATTACHMENT_TEXTURE(g_data->id_tx)
- });
-
- /* For FXAA */
- /* TODO(fclem): OPTI: we could merge normal_tx and id_tx into a GPU_RGBA8
- * and reuse it for the fxaa target. */
- g_data->color_copy = DRW_texture_pool_query_2D(size[0], size[1], GPU_RGBA8, &draw_engine_clay_type);
-
- GPU_framebuffer_ensure_config(&fbl->antialias_fb, {
- GPU_ATTACHMENT_NONE,
- GPU_ATTACHMENT_TEXTURE(g_data->color_copy)
- });
- }
-
- /* SSAO setup */
- {
- const DRWContextState *draw_ctx = DRW_context_state_get();
- Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph);
- const int ssao_samples = scene_eval->display.matcap_ssao_samples;
-
- float invproj[4][4];
- float dfdyfacs[2];
- const bool is_persp = DRW_viewport_is_persp_get();
- /* view vectors for the corners of the view frustum.
- * Can be used to recreate the world space position easily */
- float viewvecs[3][4] = {
- {-1.0f, -1.0f, -1.0f, 1.0f},
- {1.0f, -1.0f, -1.0f, 1.0f},
- {-1.0f, 1.0f, -1.0f, 1.0f}
- };
- int i;
- const float *size = DRW_viewport_size_get();
-
- DRW_state_dfdy_factors_get(dfdyfacs);
-
- g_data->ssao_params[0] = ssao_samples;
- g_data->ssao_params[1] = size[0] / 64.0;
- g_data->ssao_params[2] = size[1] / 64.0;
- g_data->ssao_params[3] = dfdyfacs[1]; /* dfdy sign for offscreen */
-
- /* invert the view matrix */
- DRW_viewport_matrix_get(g_data->winmat, DRW_MAT_WIN);
- invert_m4_m4(invproj, g_data->winmat);
-
- /* convert the view vectors to view space */
- for (i = 0; i < 3; i++) {
- mul_m4_v4(invproj, viewvecs[i]);
- /* normalized trick see:
- * http://www.derschmale.com/2014/01/26/reconstructing-positions-from-the-depth-buffer */
- mul_v3_fl(viewvecs[i], 1.0f / viewvecs[i][3]);
- if (is_persp)
- mul_v3_fl(viewvecs[i], 1.0f / viewvecs[i][2]);
- viewvecs[i][3] = 1.0;
-
- copy_v4_v4(g_data->viewvecs[i], viewvecs[i]);
- }
-
- /* we need to store the differences */
- g_data->viewvecs[1][0] -= g_data->viewvecs[0][0];
- g_data->viewvecs[1][1] = g_data->viewvecs[2][1] - g_data->viewvecs[0][1];
-
- /* calculate a depth offset as well */
- if (!is_persp) {
- float vec_far[] = {-1.0f, -1.0f, 1.0f, 1.0f};
- mul_m4_v4(invproj, vec_far);
- mul_v3_fl(vec_far, 1.0f / vec_far[3]);
- g_data->viewvecs[1][2] = vec_far[2] - g_data->viewvecs[0][2];
- }
-
- /* AO Samples Tex */
- if (sldata->sampling_ubo && (sldata->cached_sample_num != ssao_samples)) {
- DRW_UBO_FREE_SAFE(sldata->sampling_ubo);
- DRW_TEXTURE_FREE_SAFE(sldata->jitter_tx);
- }
-
- if (sldata->sampling_ubo == NULL) {
- float *samples = create_disk_samples(ssao_samples);
- sldata->jitter_tx = create_jitter_texture(ssao_samples);
- sldata->sampling_ubo = DRW_uniformbuffer_create(sizeof(float[4]) * ssao_samples, samples);
- sldata->cached_sample_num = ssao_samples;
- MEM_freeN(samples);
- }
- }
-}
-
-static DRWShadingGroup *CLAY_shgroup_create(DRWPass *pass, GPUShader *sh, int id)
-{
- CLAY_ViewLayerData *sldata = CLAY_view_layer_data_get();
- DRWShadingGroup *grp = DRW_shgroup_create(sh, pass);
- DRW_shgroup_uniform_int(grp, "mat_id", &e_data.ubo_mat_idxs[id], 1);
- if (e_data.first_shgrp) {
- DRW_shgroup_uniform_texture_persistent(grp, "matcaps", e_data.matcap_array);
- DRW_shgroup_uniform_block_persistent(grp, "material_block", sldata->mat_ubo);
- DRW_shgroup_uniform_block_persistent(grp, "matcaps_block", sldata->matcaps_ubo);
- }
- return grp;
-}
-
-static DRWShadingGroup *CLAY_shgroup_deferred_prepass_create(DRWPass *pass, GPUShader *sh, int id)
-{
- DRWShadingGroup *grp = DRW_shgroup_create(sh, pass);
- DRW_shgroup_uniform_int(grp, "mat_id", &e_data.ubo_mat_idxs[id], 1);
-
- return grp;
-}
-
-static DRWShadingGroup *CLAY_shgroup_deferred_shading_create(DRWPass *pass, CLAY_PrivateData *g_data)
-{
- CLAY_ViewLayerData *sldata = CLAY_view_layer_data_get();
- DRWShadingGroup *grp = DRW_shgroup_create(e_data.clay_deferred_shading_sh, pass);
- DRW_shgroup_uniform_texture_ref(grp, "depthtex", &g_data->depth_tx);
- DRW_shgroup_uniform_texture_ref(grp, "normaltex", &g_data->normal_tx);
- DRW_shgroup_uniform_texture_ref(grp, "idtex", &g_data->id_tx);
- DRW_shgroup_uniform_texture(grp, "matcaps", e_data.matcap_array);
- DRW_shgroup_uniform_texture(grp, "ssao_jitter", sldata->jitter_tx);
- DRW_shgroup_uniform_block(grp, "samples_block", sldata->sampling_ubo);
- DRW_shgroup_uniform_block(grp, "material_block", sldata->mat_ubo);
- DRW_shgroup_uniform_block(grp, "matcaps_block", sldata->matcaps_ubo);
- /* TODO put in ubo */
- DRW_shgroup_uniform_mat4(grp, "WinMatrix", g_data->winmat);
- DRW_shgroup_uniform_vec2(grp, "invscreenres", DRW_viewport_invert_size_get(), 1);
- DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)g_data->viewvecs, 3);
- DRW_shgroup_uniform_vec4(grp, "ssao_params", g_data->ssao_params, 1);
- return grp;
-}
-
-static DRWShadingGroup *CLAY_hair_shgroup_create(DRWPass *pass, int id)
-{
- CLAY_ViewLayerData *sldata = CLAY_view_layer_data_get();
-
- if (!e_data.hair_sh) {
- e_data.hair_sh = DRW_shader_create(
- datatoc_clay_particle_vert_glsl, NULL, datatoc_clay_particle_strand_frag_glsl,
- "#define MAX_MATERIAL " STRINGIFY(MAX_CLAY_MAT) "\n" );
- }
-
- DRWShadingGroup *grp = DRW_shgroup_create(e_data.hair_sh, pass);
- DRW_shgroup_uniform_texture(grp, "matcaps", e_data.matcap_array);
- DRW_shgroup_uniform_block(grp, "material_block", sldata->mat_ubo);
- DRW_shgroup_uniform_int(grp, "mat_id", &e_data.ubo_mat_idxs[id], 1);
-
- return grp;
-}
-
-static int search_mat_to_ubo(CLAY_Storage *storage, const CLAY_UBO_Material *mat_ubo_test)
-{
- /* For now just use a linear search and test all parameters */
- /* TODO make a hash table */
- for (int i = 0; i < storage->ubo_current_id; ++i) {
- CLAY_UBO_Material *ubo = &storage->mat_storage.materials[i];
- if (memcmp(ubo, mat_ubo_test, sizeof(*mat_ubo_test)) == 0) {
- return i;
- }
- }
-
- return -1;
-}
-
-static int search_hair_mat_to_ubo(CLAY_Storage *storage, const CLAY_HAIR_UBO_Material *hair_mat_ubo_test)
-{
- /* For now just use a linear search and test all parameters */
- /* TODO make a hash table */
- for (int i = 0; i < storage->hair_ubo_current_id; ++i) {
- CLAY_HAIR_UBO_Material *ubo = &storage->hair_mat_storage.materials[i];
- if (memcmp(ubo, hair_mat_ubo_test, sizeof(*hair_mat_ubo_test)) == 0) {
- return i;
- }
- }
-
- return -1;
-}
-
-static int push_mat_to_ubo(CLAY_Storage *storage, const CLAY_UBO_Material *mat_ubo_test)
-{
- int id = storage->ubo_current_id++;
- id = min_ii(MAX_CLAY_MAT, id);
- storage->mat_storage.materials[id] = *mat_ubo_test;
- return id;
-}
-
-static int push_hair_mat_to_ubo(CLAY_Storage *storage, const CLAY_HAIR_UBO_Material *hair_mat_ubo_test)
-{
- int id = storage->hair_ubo_current_id++;
- id = min_ii(MAX_CLAY_MAT, id);
- storage->hair_mat_storage.materials[id] = *hair_mat_ubo_test;
- return id;
-}
-
-static int mat_in_ubo(CLAY_Storage *storage, const CLAY_UBO_Material *mat_ubo_test)
-{
- /* Search material in UBO */
- int id = search_mat_to_ubo(storage, mat_ubo_test);
-
- /* if not found create it */
- if (id == -1) {
- id = push_mat_to_ubo(storage, mat_ubo_test);
- }
-
- return id;
-}
-
-static int hair_mat_in_ubo(CLAY_Storage *storage, const CLAY_HAIR_UBO_Material *hair_mat_ubo_test)
-{
- /* Search material in UBO */
- int id = search_hair_mat_to_ubo(storage, hair_mat_ubo_test);
-
- /* if not found create it */
- if (id == -1) {
- id = push_hair_mat_to_ubo(storage, hair_mat_ubo_test);
- }
-
- return id;
-}
-
-static void ubo_mat_from_object(CLAY_Storage *storage, Object *UNUSED(ob), bool *r_needs_ao, int *r_id)
-{
- const DRWContextState *draw_ctx = DRW_context_state_get();
- const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph);
-
- const int matcap_icon = scene_eval->display.matcap_icon;
- const float matcap_rot = scene_eval->display.matcap_rotation;
- const float matcap_hue = scene_eval->display.matcap_hue;
- const float matcap_sat = scene_eval->display.matcap_saturation;
- const float matcap_val = scene_eval->display.matcap_value;
- const float ssao_distance = scene_eval->display.matcap_ssao_distance;
- const float ssao_factor_cavity = scene_eval->display.matcap_ssao_factor_cavity;
- const float ssao_factor_edge = scene_eval->display.matcap_ssao_factor_edge;
- const float ssao_attenuation = scene_eval->display.matcap_ssao_attenuation;
-
- CLAY_UBO_Material r_ubo = {{0.0f}};
-
- if (((ssao_factor_cavity > 0.0) || (ssao_factor_edge > 0.0)) &&
- (ssao_distance > 0.0))
- {
- *r_needs_ao = true;
-
- r_ubo.ssao_params_var[0] = ssao_distance;
- r_ubo.ssao_params_var[1] = ssao_factor_cavity;
- r_ubo.ssao_params_var[2] = ssao_factor_edge;
- r_ubo.ssao_params_var[3] = ssao_attenuation;
- }
- else {
- *r_needs_ao = false;
- }
-
- r_ubo.matcap_rot[0] = cosf(matcap_rot * 3.14159f * 2.0f);
- r_ubo.matcap_rot[1] = sinf(matcap_rot * 3.14159f * 2.0f);
-
- r_ubo.matcap_hsv[0] = matcap_hue + 0.5f;
- r_ubo.matcap_hsv[1] = matcap_sat * 2.0f;
- r_ubo.matcap_hsv[2] = matcap_val * 2.0f;
-
- r_ubo.matcap_id = matcap_to_index(matcap_icon);
-
- *r_id = mat_in_ubo(storage, &r_ubo);
-}
-
-static void hair_ubo_mat_from_object(Object *UNUSED(ob), CLAY_HAIR_UBO_Material *r_ubo)
-{
- const DRWContextState *draw_ctx = DRW_context_state_get();
- const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph);
-
- const int matcap_icon = scene_eval->display.matcap_icon;
- const float matcap_rot = scene_eval->display.matcap_rotation;
- const float matcap_hue = scene_eval->display.matcap_hue;
- const float matcap_sat = scene_eval->display.matcap_saturation;
- const float matcap_val = scene_eval->display.matcap_value;
- const float hair_randomness = scene_eval->display.matcap_hair_brightness_randomness;
-
- memset(r_ubo, 0x0, sizeof(*r_ubo));
-
- r_ubo->matcap_rot[0] = cosf(matcap_rot * 3.14159f * 2.0f);
- r_ubo->matcap_rot[1] = sinf(matcap_rot * 3.14159f * 2.0f);
- r_ubo->matcap_hsv[0] = matcap_hue + 0.5f;
- r_ubo->matcap_hsv[1] = matcap_sat * 2.0f;
- r_ubo->matcap_hsv[2] = matcap_val * 2.0f;
- r_ubo->hair_randomness = hair_randomness;
- r_ubo->matcap_id = matcap_to_index(matcap_icon);
-}
-
-static DRWShadingGroup *CLAY_object_shgrp_get(CLAY_Data *vedata, Object *ob, bool use_flat, bool cull)
-{
- bool prepass; int id;
- CLAY_PassList *psl = vedata->psl;
- CLAY_Storage *storage = vedata->stl->storage;
- DRWShadingGroup **shgrps;
- DRWPass *pass; GPUShader *sh;
-
- ubo_mat_from_object(storage, ob, &prepass, &id);
-
- if (prepass) {
- if (use_flat) {
- shgrps = storage->shgrps_pre_flat;
- pass = (cull) ? psl->clay_flat_pre_cull_ps : psl->clay_flat_pre_ps;
- sh = e_data.clay_prepass_flat_sh;
- }
- else {
- shgrps = storage->shgrps_pre;
- pass = (cull) ? psl->clay_pre_cull_ps : psl->clay_pre_ps;
- sh = e_data.clay_prepass_sh;
- }
-
- if (shgrps[id] == NULL) {
- shgrps[id] = CLAY_shgroup_deferred_prepass_create(pass, sh, id);
- }
-
- vedata->stl->g_data->enable_deferred_path = true;
- }
- else {
- if (use_flat) {
- shgrps = storage->shgrps_flat;
- pass = (cull) ? psl->clay_flat_cull_ps : psl->clay_flat_ps;
- sh = e_data.clay_flat_sh;
- }
- else {
- shgrps = storage->shgrps;
- pass = (cull) ? psl->clay_cull_ps : psl->clay_ps;
- sh = e_data.clay_sh;
- }
-
- if (shgrps[id] == NULL) {
- shgrps[id] = CLAY_shgroup_create(pass, sh, id);
- e_data.first_shgrp = false;
- }
- }
-
- return shgrps[id];
-}
-
-static DRWShadingGroup *CLAY_hair_shgrp_get(
- CLAY_Data *UNUSED(vedata), Object *ob, CLAY_StorageList *stl, CLAY_PassList *psl)
-{
- DRWShadingGroup **hair_shgrps = stl->storage->hair_shgrps;
-
- CLAY_HAIR_UBO_Material hair_mat_ubo_test;
- hair_ubo_mat_from_object(ob, &hair_mat_ubo_test);
-
- int hair_id = hair_mat_in_ubo(stl->storage, &hair_mat_ubo_test);
-
- if (hair_shgrps[hair_id] == NULL) {
- hair_shgrps[hair_id] = CLAY_hair_shgroup_create(psl->hair_pass, hair_id);
- }
-
- return hair_shgrps[hair_id];
-}
-
-static void clay_cache_init(void *vedata)
-{
- DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
- CLAY_PassList *psl = ((CLAY_Data *)vedata)->psl;
- CLAY_StorageList *stl = ((CLAY_Data *)vedata)->stl;
-
- /* Disable AO unless a material needs it. */
- stl->g_data->enable_deferred_path = false;
-
- /* Reset UBO datas, shgrp pointers and material id counters. */
- memset(stl->storage, 0, sizeof(*stl->storage));
- e_data.first_shgrp = true;
-
- /* Solid Passes */
- {
- DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL;
- psl->clay_ps = DRW_pass_create("Clay", state);
- psl->clay_cull_ps = DRW_pass_create("Clay Culled", state | DRW_STATE_CULL_BACK);
- psl->clay_flat_ps = DRW_pass_create("Clay Flat", state);
- psl->clay_flat_cull_ps = DRW_pass_create("Clay Flat Culled", state | DRW_STATE_CULL_BACK);
-
- DRWState prepass_state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL;
- DRWState prepass_cull_state = prepass_state | DRW_STATE_CULL_BACK;
- psl->clay_pre_ps = DRW_pass_create("Clay Deferred Pre", prepass_state);
- psl->clay_pre_cull_ps = DRW_pass_create("Clay Deferred Pre Culled", prepass_cull_state);
- psl->clay_flat_pre_ps = DRW_pass_create("Clay Deferred Flat Pre", prepass_state);
- psl->clay_flat_pre_cull_ps = DRW_pass_create("Clay Deferred Flat Pre Culled", prepass_cull_state);
-
- psl->clay_deferred_ps = DRW_pass_create("Clay Deferred Shading", DRW_STATE_WRITE_COLOR);
- DRWShadingGroup *grp = CLAY_shgroup_deferred_shading_create(psl->clay_deferred_ps, stl->g_data);
- DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL);
- }
-
- /* Hair Pass */
- {
- psl->hair_pass = DRW_pass_create(
- "Hair Pass",
- DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_WIRE);
- }
-
- {
- psl->fxaa_ps = DRW_pass_create("Fxaa", DRW_STATE_WRITE_COLOR);
- DRWShadingGroup *grp = DRW_shgroup_create(e_data.fxaa_sh, psl->fxaa_ps);
- DRW_shgroup_uniform_texture_ref(grp, "colortex", &dtxl->color);
- DRW_shgroup_uniform_vec2(grp, "invscreenres", DRW_viewport_invert_size_get(), 1);
- DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL);
-
- psl->copy_ps = DRW_pass_create("Copy", DRW_STATE_WRITE_COLOR);
- grp = DRW_shgroup_create(e_data.copy_sh, psl->copy_ps);
- DRW_shgroup_uniform_texture_ref(grp, "colortex", &stl->g_data->color_copy);
- DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL);
- }
-}
-
-static void clay_cache_populate_particles(void *vedata, Object *ob)
-{
- CLAY_PassList *psl = ((CLAY_Data *)vedata)->psl;
- CLAY_StorageList *stl = ((CLAY_Data *)vedata)->stl;
- const DRWContextState *draw_ctx = DRW_context_state_get();
-
- if (ob == draw_ctx->object_edit) {
- return;
- }
-
- for (ParticleSystem *psys = ob->particlesystem.first; psys; psys = psys->next) {
- if (!psys_check_enabled(ob, psys, false)) {
- continue;
- }
- if (!DRW_check_psys_visible_within_active_context(ob, psys)) {
- continue;
- }
- ParticleSettings *part = psys->part;
- const int draw_as = (part->draw_as == PART_DRAW_REND) ? part->ren_as : part->draw_as;
- if (draw_as == PART_DRAW_PATH) {
- struct Gwn_Batch *geom = DRW_cache_particles_get_hair(ob, psys, NULL);
- DRWShadingGroup *hair_shgrp = CLAY_hair_shgrp_get(vedata, ob, stl, psl);
- DRW_shgroup_call_add(hair_shgrp, geom, NULL);
- }
- }
-}
-
-static void clay_cache_populate(void *vedata, Object *ob)
-{
- DRWShadingGroup *clay_shgrp;
-
- if (!DRW_object_is_renderable(ob))
- return;
-
- const DRWContextState *draw_ctx = DRW_context_state_get();
- const bool is_active = (ob == draw_ctx->obact);
- if (is_active) {
- if (DRW_object_is_mode_shade(ob) == true) {
- return;
- }
- }
-
- /* Handle particles first in case the emitter itself shouldn't be rendered. */
- if (ob->type == OB_MESH) {
- clay_cache_populate_particles(vedata, ob);
- }
-
- if (DRW_check_object_visible_within_active_context(ob) == false) {
- return;
- }
-
- struct Gwn_Batch *geom = DRW_cache_object_surface_get(ob);
- if (geom) {
- const bool do_cull = (draw_ctx->v3d && (draw_ctx->v3d->flag2 & V3D_BACKFACE_CULLING));
- const bool is_sculpt_mode = is_active && (draw_ctx->object_mode & OB_MODE_SCULPT) != 0;
- const bool use_flat = is_sculpt_mode && DRW_object_is_flat_normal(ob);
-
- clay_shgrp = CLAY_object_shgrp_get(vedata, ob, use_flat, do_cull);
-
- if (is_sculpt_mode) {
- DRW_shgroup_call_sculpt_add(clay_shgrp, ob, ob->obmat);
- }
- else {
- DRW_shgroup_call_object_add(clay_shgrp, geom, ob);
- }
- }
-}
-
-static void clay_cache_finish(void *vedata)
-{
- CLAY_ViewLayerData *sldata = CLAY_view_layer_data_get();
- CLAY_StorageList *stl = ((CLAY_Data *)vedata)->stl;
-
- DRW_uniformbuffer_update(sldata->mat_ubo, &stl->storage->mat_storage);
- DRW_uniformbuffer_update(sldata->hair_mat_ubo, &stl->storage->hair_mat_storage);
-}
-
-static void clay_draw_scene(void *vedata)
-{
- CLAY_StorageList *stl = ((CLAY_Data *)vedata)->stl;
- CLAY_PassList *psl = ((CLAY_Data *)vedata)->psl;
- CLAY_FramebufferList *fbl = ((CLAY_Data *)vedata)->fbl;
- DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
- DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
- stl->g_data->depth_tx = dtxl->depth;
-
- /* Passes are ordered to have less _potential_ overdraw */
- DRW_draw_pass(psl->clay_cull_ps);
- DRW_draw_pass(psl->clay_flat_cull_ps);
- DRW_draw_pass(psl->clay_ps);
- DRW_draw_pass(psl->clay_flat_ps);
- DRW_draw_pass(psl->hair_pass);
-
- if (stl->g_data->enable_deferred_path) {
- GPU_framebuffer_bind(fbl->prepass_fb);
- /* We need to clear the id texture unfortunately. */
- const float clear_col[4] = {0.0f, 0.0f, 0.0f, 0.0f};
- GPU_framebuffer_clear_color(fbl->prepass_fb, clear_col);
-
- DRW_draw_pass(psl->clay_pre_cull_ps);
- DRW_draw_pass(psl->clay_flat_pre_cull_ps);
- DRW_draw_pass(psl->clay_pre_ps);
- DRW_draw_pass(psl->clay_flat_pre_ps);
-
- GPU_framebuffer_bind(dfbl->color_only_fb);
- DRW_draw_pass(psl->clay_deferred_ps);
- }
-
- if (true) { /* Always on for now. We might want a parameter for this. */
- GPU_framebuffer_bind(fbl->antialias_fb);
- DRW_draw_pass(psl->fxaa_ps);
-
- GPU_framebuffer_bind(dfbl->color_only_fb);
- DRW_draw_pass(psl->copy_ps);
- }
-}
-
-static void clay_engine_free(void)
-{
- DRW_SHADER_FREE_SAFE(e_data.clay_sh);
- DRW_SHADER_FREE_SAFE(e_data.clay_flat_sh);
- DRW_SHADER_FREE_SAFE(e_data.clay_prepass_flat_sh);
- DRW_SHADER_FREE_SAFE(e_data.clay_prepass_sh);
- DRW_SHADER_FREE_SAFE(e_data.clay_deferred_shading_sh);
- DRW_SHADER_FREE_SAFE(e_data.fxaa_sh);
- DRW_SHADER_FREE_SAFE(e_data.copy_sh);
- DRW_SHADER_FREE_SAFE(e_data.hair_sh);
- DRW_TEXTURE_FREE_SAFE(e_data.matcap_array);
-}
-
-static const DrawEngineDataSize clay_data_size = DRW_VIEWPORT_DATA_SIZE(CLAY_Data);
-
-DrawEngineType draw_engine_clay_type = {
- NULL, NULL,
- N_("Clay"),
- &clay_data_size,
- &clay_engine_init,
- &clay_engine_free,
- &clay_cache_init,
- &clay_cache_populate,
- &clay_cache_finish,
- NULL,
- &clay_draw_scene,
- NULL,
- NULL,
- NULL,
-};
-
-RenderEngineType DRW_engine_viewport_clay_type = {
- NULL, NULL,
- CLAY_ENGINE, N_("Clay"), RE_INTERNAL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- &draw_engine_clay_type,
- {NULL, NULL, NULL}
-};
-
-
-#undef CLAY_ENGINE
-
-#endif /* WITH_CLAY_ENGINE */