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:
authorClément Foucault <foucault.clem@gmail.com>2017-04-03 16:38:00 +0300
committerClément Foucault <foucault.clem@gmail.com>2017-04-03 22:52:03 +0300
commiteca256bc327813f2d3ce29e8e89e07c4c0294403 (patch)
tree152bc878fd252df801fd9df9a8d4809fd7fe1e3d
parent8e0bfee1e5e68a4208a10951586d1b7504222a89 (diff)
GPULamp: Separate GPULamp from GPUMaterial
Since we need GPULamps for draw engines, it makes sense to separate them.
-rw-r--r--source/blender/blenkernel/intern/object.c2
-rw-r--r--source/blender/editors/object/object_add.c2
-rw-r--r--source/blender/editors/render/render_update.c1
-rw-r--r--source/blender/editors/space_view3d/view3d_draw_legacy.c1
-rw-r--r--source/blender/gpu/CMakeLists.txt2
-rw-r--r--source/blender/gpu/GPU_lamp.h75
-rw-r--r--source/blender/gpu/GPU_material.h24
-rw-r--r--source/blender/gpu/intern/gpu_lamp.c475
-rw-r--r--source/blender/gpu/intern/gpu_lamp_private.h86
-rw-r--r--source/blender/gpu/intern/gpu_material.c441
-rw-r--r--source/blender/nodes/shader/node_shader_util.h1
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLLight.cpp1
12 files changed, 648 insertions, 463 deletions
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index 8b306a9ae14..7250fd279c7 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -129,7 +129,7 @@
#include "CCGSubSurf.h"
-#include "GPU_material.h"
+#include "GPU_lamp.h"
/* Vertex parent modifies original BMesh which is not safe for threading.
* Ideally such a modification should be handled as a separate DAG update
diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c
index adfd213ff3e..4852ae0741e 100644
--- a/source/blender/editors/object/object_add.c
+++ b/source/blender/editors/object/object_add.c
@@ -115,7 +115,7 @@
#include "UI_resources.h"
-#include "GPU_material.h"
+#include "GPU_lamp.h"
#include "object_intern.h"
diff --git a/source/blender/editors/render/render_update.c b/source/blender/editors/render/render_update.c
index 899b9e0ece7..46c3417e8c2 100644
--- a/source/blender/editors/render/render_update.c
+++ b/source/blender/editors/render/render_update.c
@@ -55,6 +55,7 @@
#include "BKE_paint.h"
#include "BKE_scene.h"
+#include "GPU_lamp.h"
#include "GPU_material.h"
#include "GPU_buffers.h"
diff --git a/source/blender/editors/space_view3d/view3d_draw_legacy.c b/source/blender/editors/space_view3d/view3d_draw_legacy.c
index 3d43bc011e6..edf2273cd35 100644
--- a/source/blender/editors/space_view3d/view3d_draw_legacy.c
+++ b/source/blender/editors/space_view3d/view3d_draw_legacy.c
@@ -97,6 +97,7 @@
#include "GPU_draw.h"
#include "GPU_framebuffer.h"
+#include "GPU_lamp.h"
#include "GPU_material.h"
#include "GPU_compositing.h"
#include "GPU_extensions.h"
diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt
index 42eb9cdcd32..049ee3d3f64 100644
--- a/source/blender/gpu/CMakeLists.txt
+++ b/source/blender/gpu/CMakeLists.txt
@@ -61,6 +61,7 @@ set(SRC
intern/gpu_framebuffer.c
intern/gpu_immediate.c
intern/gpu_init_exit.c
+ intern/gpu_lamp.c
intern/gpu_material.c
intern/gpu_matrix.c
intern/gpu_select.c
@@ -114,6 +115,7 @@ set(SRC
intern/gpu_codegen.h
intern/gpu_private.h
+ intern/gpu_lamp_private.h
intern/gpu_select_private.h
intern/gpu_shader_private.h
)
diff --git a/source/blender/gpu/GPU_lamp.h b/source/blender/gpu/GPU_lamp.h
new file mode 100644
index 00000000000..32793830479
--- /dev/null
+++ b/source/blender/gpu/GPU_lamp.h
@@ -0,0 +1,75 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * 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.
+ *
+ * The Original Code is Copyright (C) 2005 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Brecht Van Lommel, Clément Foucault.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file GPU_lamp.h
+ * \ingroup gpu
+ */
+
+#ifndef __GPU_LAMP_H__
+#define __GPU_LAMP_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct Scene;
+struct Object;
+struct RenderEngineType;
+
+typedef struct GPULamp GPULamp;
+
+typedef struct LampEngineData {
+ struct GPUFrameBuffer *framebuffers[4];
+ struct GPUTexture *textures[4];
+ void *storage[4];
+} LampEngineData;
+
+GPULamp *GPU_lamp_from_engine(struct Scene *scene, struct Object *ob, Object *par, struct RenderEngineType *re);
+GPULamp *GPU_lamp_from_blender(struct Scene *scene, struct Object *ob, struct Object *par);
+void GPU_lamp_free(struct Object *ob);
+
+bool GPU_lamp_override_visible(GPULamp *lamp, struct SceneRenderLayer *srl, struct Material *ma);
+bool GPU_lamp_has_shadow_buffer(GPULamp *lamp);
+void GPU_lamp_update_buffer_mats(GPULamp *lamp);
+void GPU_lamp_shadow_buffer_bind(GPULamp *lamp, float viewmat[4][4], int *winsize, float winmat[4][4]);
+void GPU_lamp_shadow_buffer_unbind(GPULamp *lamp);
+int GPU_lamp_shadow_buffer_type(GPULamp *lamp);
+int GPU_lamp_shadow_bind_code(GPULamp *lamp);
+float *GPU_lamp_dynpersmat(GPULamp *lamp);
+
+void GPU_lamp_update(GPULamp *lamp, int lay, int hide, float obmat[4][4]);
+void GPU_lamp_update_colors(GPULamp *lamp, float r, float g, float b, float energy);
+void GPU_lamp_update_distance(GPULamp *lamp, float distance, float att1, float att2,
+ float coeff_const, float coeff_lin, float coeff_quad);
+void GPU_lamp_update_spot(GPULamp *lamp, float spotsize, float spotblend);
+int GPU_lamp_shadow_layer(GPULamp *lamp);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __GPU_LAMP_H__ */
diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h
index 0d92d22a173..cbcd6383a72 100644
--- a/source/blender/gpu/GPU_material.h
+++ b/source/blender/gpu/GPU_material.h
@@ -45,7 +45,6 @@ struct Image;
struct ImageUser;
struct Material;
struct Object;
-struct Image;
struct Scene;
struct SceneRenderLayer;
struct GPUVertexAttribs;
@@ -61,7 +60,7 @@ struct World;
typedef struct GPUNode GPUNode;
typedef struct GPUNodeLink GPUNodeLink;
typedef struct GPUMaterial GPUMaterial;
-typedef struct GPULamp GPULamp;
+
typedef struct GPUParticleInfo GPUParticleInfo;
/* Functions to create GPU Materials nodes */
@@ -224,7 +223,6 @@ void GPU_material_free(struct ListBase *gpumaterial);
void GPU_materials_free(void);
-bool GPU_lamp_override_visible(GPULamp *lamp, struct SceneRenderLayer *srl, struct Material *ma);
void GPU_material_bind(
GPUMaterial *material, int oblay, int viewlay, double time, int mipmap,
float viewmat[4][4], float viewinv[4][4], float cameraborder[4], bool scenelock);
@@ -310,26 +308,8 @@ GPUShaderExport *GPU_shader_export(struct Scene *scene, struct Material *ma);
void GPU_free_shader_export(GPUShaderExport *shader);
/* Lamps */
-
-GPULamp *GPU_lamp_from_blender(struct Scene *scene, struct Object *ob, struct Object *par);
-void GPU_lamp_free(struct Object *ob);
-
-bool GPU_lamp_has_shadow_buffer(GPULamp *lamp);
-void GPU_lamp_update_buffer_mats(GPULamp *lamp);
-void GPU_lamp_shadow_buffer_bind(GPULamp *lamp, float viewmat[4][4], int *winsize, float winmat[4][4]);
-void GPU_lamp_shadow_buffer_unbind(GPULamp *lamp);
-int GPU_lamp_shadow_buffer_type(GPULamp *lamp);
-int GPU_lamp_shadow_bind_code(GPULamp *lamp);
-float *GPU_lamp_dynpersmat(GPULamp *lamp);
-
-void GPU_lamp_update(GPULamp *lamp, int lay, int hide, float obmat[4][4]);
-void GPU_lamp_update_colors(GPULamp *lamp, float r, float g, float b, float energy);
-void GPU_lamp_update_distance(GPULamp *lamp, float distance, float att1, float att2,
- float coeff_const, float coeff_lin, float coeff_quad);
-void GPU_lamp_update_spot(GPULamp *lamp, float spotsize, float spotblend);
-int GPU_lamp_shadow_layer(GPULamp *lamp);
GPUNodeLink *GPU_lamp_get_data(
- GPUMaterial *mat, GPULamp *lamp,
+ GPUMaterial *mat, struct GPULamp *lamp,
GPUNodeLink **r_col, GPUNodeLink **r_lv, GPUNodeLink **r_dist, GPUNodeLink **r_shadow, GPUNodeLink **r_energy);
/* World */
diff --git a/source/blender/gpu/intern/gpu_lamp.c b/source/blender/gpu/intern/gpu_lamp.c
new file mode 100644
index 00000000000..ee0bcb83a6a
--- /dev/null
+++ b/source/blender/gpu/intern/gpu_lamp.c
@@ -0,0 +1,475 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * 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.
+ *
+ * The Original Code is Copyright (C) 2006 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Brecht Van Lommel, Clément Foucault.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/gpu/intern/gpu_lamp.c
+ * \ingroup gpu
+ *
+ * Manages Opengl lights.
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_lamp_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+
+#include "BLI_listbase.h"
+#include "BLI_math.h"
+#include "BLI_utildefines.h"
+
+#include "BKE_group.h"
+
+#include "GPU_framebuffer.h"
+#include "GPU_glew.h"
+#include "GPU_lamp.h"
+#include "GPU_material.h"
+#include "GPU_shader.h"
+#include "GPU_texture.h"
+
+#include "gpu_lamp_private.h"
+
+bool GPU_lamp_override_visible(GPULamp *lamp, SceneRenderLayer *srl, Material *ma)
+{
+ if (srl && srl->light_override)
+ return BKE_group_object_exists(srl->light_override, lamp->ob);
+ else if (ma && ma->group)
+ return BKE_group_object_exists(ma->group, lamp->ob);
+ else
+ return true;
+}
+
+static void gpu_lamp_calc_winmat(GPULamp *lamp)
+{
+ float temp, angle, pixsize, wsize;
+
+ if (lamp->type == LA_SUN) {
+ wsize = lamp->la->shadow_frustum_size;
+ orthographic_m4(lamp->winmat, -wsize, wsize, -wsize, wsize, lamp->d, lamp->clipend);
+ }
+ else if (lamp->type == LA_SPOT) {
+ angle = saacos(lamp->spotsi);
+ temp = 0.5f * lamp->size * cosf(angle) / sinf(angle);
+ pixsize = lamp->d / temp;
+ wsize = pixsize * 0.5f * lamp->size;
+ /* compute shadows according to X and Y scaling factors */
+ perspective_m4(
+ lamp->winmat,
+ -wsize * lamp->spotvec[0], wsize * lamp->spotvec[0],
+ -wsize * lamp->spotvec[1], wsize * lamp->spotvec[1],
+ lamp->d, lamp->clipend);
+ }
+}
+
+void GPU_lamp_update(GPULamp *lamp, int lay, int hide, float obmat[4][4])
+{
+ float mat[4][4];
+ float obmat_scale[3];
+
+ lamp->lay = lay;
+ lamp->hide = hide;
+
+ normalize_m4_m4_ex(mat, obmat, obmat_scale);
+
+ copy_v3_v3(lamp->vec, mat[2]);
+ copy_v3_v3(lamp->co, mat[3]);
+ copy_m4_m4(lamp->obmat, mat);
+ invert_m4_m4(lamp->imat, mat);
+
+ if (lamp->type == LA_SPOT) {
+ /* update spotlamp scale on X and Y axis */
+ lamp->spotvec[0] = obmat_scale[0] / obmat_scale[2];
+ lamp->spotvec[1] = obmat_scale[1] / obmat_scale[2];
+ }
+
+ if (GPU_lamp_has_shadow_buffer(lamp)) {
+ /* makeshadowbuf */
+ gpu_lamp_calc_winmat(lamp);
+ }
+}
+
+void GPU_lamp_update_colors(GPULamp *lamp, float r, float g, float b, float energy)
+{
+ lamp->energy = energy;
+ if (lamp->mode & LA_NEG) lamp->energy = -lamp->energy;
+
+ lamp->col[0] = r;
+ lamp->col[1] = g;
+ lamp->col[2] = b;
+}
+
+void GPU_lamp_update_distance(GPULamp *lamp, float distance, float att1, float att2,
+ float coeff_const, float coeff_lin, float coeff_quad)
+{
+ lamp->dist = distance;
+ lamp->att1 = att1;
+ lamp->att2 = att2;
+ lamp->coeff_const = coeff_const;
+ lamp->coeff_lin = coeff_lin;
+ lamp->coeff_quad = coeff_quad;
+}
+
+void GPU_lamp_update_spot(GPULamp *lamp, float spotsize, float spotblend)
+{
+ lamp->spotsi = cosf(spotsize * 0.5f);
+ lamp->spotbl = (1.0f - lamp->spotsi) * spotblend;
+}
+
+static void gpu_lamp_from_blender(Scene *scene, Object *ob, Object *par, Lamp *la, GPULamp *lamp)
+{
+ lamp->scene = scene;
+ lamp->ob = ob;
+ lamp->par = par;
+ lamp->la = la;
+
+ /* add_render_lamp */
+ lamp->mode = la->mode;
+ lamp->type = la->type;
+
+ lamp->energy = la->energy;
+ if (lamp->mode & LA_NEG) lamp->energy = -lamp->energy;
+
+ lamp->col[0] = la->r;
+ lamp->col[1] = la->g;
+ lamp->col[2] = la->b;
+
+ GPU_lamp_update(lamp, ob->lay, (ob->restrictflag & OB_RESTRICT_RENDER), ob->obmat);
+
+ lamp->spotsi = la->spotsize;
+ if (lamp->mode & LA_HALO)
+ if (lamp->spotsi > DEG2RADF(170.0f))
+ lamp->spotsi = DEG2RADF(170.0f);
+ lamp->spotsi = cosf(lamp->spotsi * 0.5f);
+ lamp->spotbl = (1.0f - lamp->spotsi) * la->spotblend;
+ lamp->k = la->k;
+
+ lamp->dist = la->dist;
+ lamp->falloff_type = la->falloff_type;
+ lamp->att1 = la->att1;
+ lamp->att2 = la->att2;
+ lamp->coeff_const = la->coeff_const;
+ lamp->coeff_lin = la->coeff_lin;
+ lamp->coeff_quad = la->coeff_quad;
+ lamp->curfalloff = la->curfalloff;
+
+ /* initshadowbuf */
+ lamp->bias = 0.02f * la->bias;
+ lamp->size = la->bufsize;
+ lamp->d = la->clipsta;
+ lamp->clipend = la->clipend;
+
+ /* arbitrary correction for the fact we do no soft transition */
+ lamp->bias *= 0.25f;
+}
+
+static void gpu_lamp_shadow_free(GPULamp *lamp)
+{
+ if (lamp->tex) {
+ GPU_texture_free(lamp->tex);
+ lamp->tex = NULL;
+ }
+ if (lamp->depthtex) {
+ GPU_texture_free(lamp->depthtex);
+ lamp->depthtex = NULL;
+ }
+ if (lamp->fb) {
+ GPU_framebuffer_free(lamp->fb);
+ lamp->fb = NULL;
+ }
+ if (lamp->blurtex) {
+ GPU_texture_free(lamp->blurtex);
+ lamp->blurtex = NULL;
+ }
+ if (lamp->blurfb) {
+ GPU_framebuffer_free(lamp->blurfb);
+ lamp->blurfb = NULL;
+ }
+}
+
+static GPUTexture *gpu_lamp_create_vsm_shadow_map(int size)
+{
+ return GPU_texture_create_2D_custom(size, size, 2, GPU_RG32F, NULL, NULL);
+}
+
+GPULamp *GPU_lamp_from_engine(Scene *scene, Object *ob, Object *par, struct RenderEngineType *re)
+{
+ GPULamp *lamp;
+ LinkData *link;
+
+ for (link = ob->gpulamp.first; link; link = link->next) {
+ lamp = (GPULamp *)link->data;
+
+ if ((lamp->par == par) && (lamp->scene == scene) && (lamp->re == re))
+ return link->data;
+ }
+
+ lamp = MEM_callocN(sizeof(GPULamp), "GPULamp");
+
+ link = MEM_callocN(sizeof(LinkData), "GPULampLink");
+ link->data = lamp;
+ BLI_addtail(&ob->gpulamp, link);
+
+ lamp->scene = scene;
+ lamp->ob = ob;
+ lamp->par = par;
+ lamp->la = ob->data;
+ lamp->re = re;
+
+ return lamp;
+}
+
+GPULamp *GPU_lamp_from_blender(Scene *scene, Object *ob, Object *par)
+{
+ Lamp *la;
+ GPULamp *lamp;
+ LinkData *link;
+
+ for (link = ob->gpulamp.first; link; link = link->next) {
+ lamp = (GPULamp *)link->data;
+
+ if (lamp->par == par && lamp->scene == scene)
+ return link->data;
+ }
+
+ lamp = MEM_callocN(sizeof(GPULamp), "GPULamp");
+
+ link = MEM_callocN(sizeof(LinkData), "GPULampLink");
+ link->data = lamp;
+ BLI_addtail(&ob->gpulamp, link);
+
+ la = ob->data;
+ gpu_lamp_from_blender(scene, ob, par, la, lamp);
+
+ if ((la->type == LA_SPOT && (la->mode & (LA_SHAD_BUF | LA_SHAD_RAY))) ||
+ (la->type == LA_SUN && (la->mode & LA_SHAD_RAY)))
+ {
+ /* opengl */
+ lamp->fb = GPU_framebuffer_create();
+ if (!lamp->fb) {
+ gpu_lamp_shadow_free(lamp);
+ return lamp;
+ }
+
+ if (lamp->la->shadowmap_type == LA_SHADMAP_VARIANCE) {
+ /* Shadow depth map */
+ lamp->depthtex = GPU_texture_create_depth(lamp->size, lamp->size, NULL);
+ if (!lamp->depthtex) {
+ gpu_lamp_shadow_free(lamp);
+ return lamp;
+ }
+
+ if (!GPU_framebuffer_texture_attach(lamp->fb, lamp->depthtex, 0)) {
+ gpu_lamp_shadow_free(lamp);
+ return lamp;
+ }
+
+ /* Shadow color map */
+ lamp->tex = gpu_lamp_create_vsm_shadow_map(lamp->size);
+ if (!lamp->tex) {
+ gpu_lamp_shadow_free(lamp);
+ return lamp;
+ }
+
+ if (!GPU_framebuffer_texture_attach(lamp->fb, lamp->tex, 0)) {
+ gpu_lamp_shadow_free(lamp);
+ return lamp;
+ }
+
+ if (!GPU_framebuffer_check_valid(lamp->fb, NULL)) {
+ gpu_lamp_shadow_free(lamp);
+ return lamp;
+ }
+
+ /* FBO and texture for blurring */
+ lamp->blurfb = GPU_framebuffer_create();
+ if (!lamp->blurfb) {
+ gpu_lamp_shadow_free(lamp);
+ return lamp;
+ }
+
+ lamp->blurtex = gpu_lamp_create_vsm_shadow_map(lamp->size * 0.5);
+ if (!lamp->blurtex) {
+ gpu_lamp_shadow_free(lamp);
+ return lamp;
+ }
+
+ if (!GPU_framebuffer_texture_attach(lamp->blurfb, lamp->blurtex, 0)) {
+ gpu_lamp_shadow_free(lamp);
+ return lamp;
+ }
+
+ /* we need to properly bind to test for completeness */
+ GPU_texture_bind_as_framebuffer(lamp->blurtex);
+
+ if (!GPU_framebuffer_check_valid(lamp->blurfb, NULL)) {
+ gpu_lamp_shadow_free(lamp);
+ return lamp;
+ }
+
+ GPU_framebuffer_texture_unbind(lamp->blurfb, lamp->blurtex);
+ }
+ else {
+ lamp->tex = GPU_texture_create_depth(lamp->size, lamp->size, NULL);
+ if (!lamp->tex) {
+ gpu_lamp_shadow_free(lamp);
+ return lamp;
+ }
+
+ if (!GPU_framebuffer_texture_attach(lamp->fb, lamp->tex, 0)) {
+ gpu_lamp_shadow_free(lamp);
+ return lamp;
+ }
+
+ if (!GPU_framebuffer_check_valid(lamp->fb, NULL)) {
+ gpu_lamp_shadow_free(lamp);
+ return lamp;
+ }
+ }
+
+ GPU_framebuffer_restore();
+
+ lamp->shadow_color[0] = la->shdwr;
+ lamp->shadow_color[1] = la->shdwg;
+ lamp->shadow_color[2] = la->shdwb;
+ }
+ else {
+ lamp->shadow_color[0] = 1.0;
+ lamp->shadow_color[1] = 1.0;
+ lamp->shadow_color[2] = 1.0;
+ }
+
+ return lamp;
+}
+
+void GPU_lamp_free(Object *ob)
+{
+ GPULamp *lamp;
+ LinkData *link;
+ LinkData *nlink;
+ Material *ma;
+
+ for (link = ob->gpulamp.first; link; link = link->next) {
+ lamp = link->data;
+
+ while (lamp->materials.first) {
+ nlink = lamp->materials.first;
+ ma = nlink->data;
+ BLI_freelinkN(&lamp->materials, nlink);
+
+ if (ma->gpumaterial.first)
+ GPU_material_free(&ma->gpumaterial);
+ }
+
+ gpu_lamp_shadow_free(lamp);
+
+ MEM_freeN(lamp);
+ }
+
+ BLI_freelistN(&ob->gpulamp);
+}
+
+bool GPU_lamp_has_shadow_buffer(GPULamp *lamp)
+{
+ return (!(lamp->scene->gm.flag & GAME_GLSL_NO_SHADOWS) &&
+ !(lamp->scene->gm.flag & GAME_GLSL_NO_LIGHTS) &&
+ lamp->tex && lamp->fb);
+}
+
+void GPU_lamp_update_buffer_mats(GPULamp *lamp)
+{
+ float rangemat[4][4], persmat[4][4];
+
+ /* initshadowbuf */
+ invert_m4_m4(lamp->viewmat, lamp->obmat);
+ normalize_v3(lamp->viewmat[0]);
+ normalize_v3(lamp->viewmat[1]);
+ normalize_v3(lamp->viewmat[2]);
+
+ /* makeshadowbuf */
+ mul_m4_m4m4(persmat, lamp->winmat, lamp->viewmat);
+
+ /* opengl depth buffer is range 0.0..1.0 instead of -1.0..1.0 in blender */
+ unit_m4(rangemat);
+ rangemat[0][0] = 0.5f;
+ rangemat[1][1] = 0.5f;
+ rangemat[2][2] = 0.5f;
+ rangemat[3][0] = 0.5f;
+ rangemat[3][1] = 0.5f;
+ rangemat[3][2] = 0.5f;
+
+ mul_m4_m4m4(lamp->persmat, rangemat, persmat);
+}
+
+void GPU_lamp_shadow_buffer_bind(GPULamp *lamp, float viewmat[4][4], int *winsize, float winmat[4][4])
+{
+ GPU_lamp_update_buffer_mats(lamp);
+
+ /* opengl */
+ glDisable(GL_SCISSOR_TEST);
+ GPU_texture_bind_as_framebuffer(lamp->tex);
+ if (lamp->la->shadowmap_type == LA_SHADMAP_VARIANCE)
+ GPU_shader_bind(GPU_shader_get_builtin_shader(GPU_SHADER_VSM_STORE));
+
+ /* set matrices */
+ copy_m4_m4(viewmat, lamp->viewmat);
+ copy_m4_m4(winmat, lamp->winmat);
+ *winsize = lamp->size;
+}
+
+void GPU_lamp_shadow_buffer_unbind(GPULamp *lamp)
+{
+ if (lamp->la->shadowmap_type == LA_SHADMAP_VARIANCE) {
+ GPU_shader_unbind();
+ GPU_framebuffer_blur(lamp->fb, lamp->tex, lamp->blurfb, lamp->blurtex);
+ }
+
+ GPU_framebuffer_texture_unbind(lamp->fb, lamp->tex);
+ GPU_framebuffer_restore();
+ glEnable(GL_SCISSOR_TEST);
+}
+
+int GPU_lamp_shadow_buffer_type(GPULamp *lamp)
+{
+ return lamp->la->shadowmap_type;
+}
+
+int GPU_lamp_shadow_bind_code(GPULamp *lamp)
+{
+ return lamp->tex ? GPU_texture_opengl_bindcode(lamp->tex) : -1;
+}
+
+float *GPU_lamp_dynpersmat(GPULamp *lamp)
+{
+ return &lamp->dynpersmat[0][0];
+}
+
+int GPU_lamp_shadow_layer(GPULamp *lamp)
+{
+ if (lamp->fb && lamp->tex && (lamp->mode & (LA_LAYER | LA_LAYER_SHADOW)))
+ return lamp->lay;
+ else
+ return -1;
+}
diff --git a/source/blender/gpu/intern/gpu_lamp_private.h b/source/blender/gpu/intern/gpu_lamp_private.h
new file mode 100644
index 00000000000..ef71385e66d
--- /dev/null
+++ b/source/blender/gpu/intern/gpu_lamp_private.h
@@ -0,0 +1,86 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * 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.
+ *
+ * The Original Code is Copyright (C) 2005 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Brecht Van Lommel, Clément Foucault.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file gpu_lamp_private.h
+ * \ingroup gpu
+ */
+
+#ifndef __GPU_LAMP_PRIVATE_H__
+#define __GPU_LAMP_PRIVATE_H__
+
+#include "BLI_sys_types.h" /* for bool */
+
+struct GPULamp {
+ Scene *scene;
+ Object *ob;
+ Object *par;
+ Lamp *la;
+ struct RenderEngineType *re;
+
+ /* Old Viewport (pre-2.8) */
+ int type, mode, lay, hide;
+
+ float dynenergy, dyncol[3];
+ float energy, col[3];
+
+ float co[3], vec[3];
+ float dynco[3], dynvec[3];
+ float obmat[4][4];
+ float imat[4][4];
+ float dynimat[4][4];
+
+ float spotsi, spotbl, k;
+ float spotvec[2];
+ float dyndist, dynatt1, dynatt2;
+ float dist, att1, att2;
+ float coeff_const, coeff_lin, coeff_quad;
+ float shadow_color[3];
+
+ float bias, d, clipend;
+ int size;
+
+ int falloff_type;
+ struct CurveMapping *curfalloff;
+
+ float winmat[4][4];
+ float viewmat[4][4];
+ float persmat[4][4];
+ float dynpersmat[4][4];
+
+ GPUFrameBuffer *fb;
+ GPUFrameBuffer *blurfb;
+ GPUTexture *tex;
+ GPUTexture *depthtex;
+ GPUTexture *blurtex;
+
+ ListBase materials;
+
+ /* New viewport */
+ struct LampEngineData data;
+};
+
+#endif /* __GPU_LAMP_PRIVATE_H__ */
diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c
index 28cf7bd1c76..153ae8ec8dc 100644
--- a/source/blender/gpu/intern/gpu_material.c
+++ b/source/blender/gpu/intern/gpu_material.c
@@ -60,11 +60,13 @@
#include "GPU_extensions.h"
#include "GPU_framebuffer.h"
+#include "GPU_lamp.h"
#include "GPU_material.h"
#include "GPU_shader.h"
#include "GPU_texture.h"
#include "gpu_codegen.h"
+#include "gpu_lamp_private.h"
#ifdef WITH_OPENSUBDIV
# include "BKE_DerivedMesh.h"
@@ -128,50 +130,6 @@ struct GPUMaterial {
bool is_opensubdiv;
};
-struct GPULamp {
- Scene *scene;
- Object *ob;
- Object *par;
- Lamp *la;
-
- int type, mode, lay, hide;
-
- float dynenergy, dyncol[3];
- float energy, col[3];
-
- float co[3], vec[3];
- float dynco[3], dynvec[3];
- float obmat[4][4];
- float imat[4][4];
- float dynimat[4][4];
-
- float spotsi, spotbl, k;
- float spotvec[2];
- float dyndist, dynatt1, dynatt2;
- float dist, att1, att2;
- float coeff_const, coeff_lin, coeff_quad;
- float shadow_color[3];
-
- float bias, d, clipend;
- int size;
-
- int falloff_type;
- struct CurveMapping *curfalloff;
-
- float winmat[4][4];
- float viewmat[4][4];
- float persmat[4][4];
- float dynpersmat[4][4];
-
- GPUFrameBuffer *fb;
- GPUFrameBuffer *blurfb;
- GPUTexture *tex;
- GPUTexture *depthtex;
- GPUTexture *blurtex;
-
- ListBase materials;
-};
-
/* Forward declaration so shade_light_textures() can use this, while still keeping the code somewhat organized */
static void texture_rgb_blend(
GPUMaterial *mat, GPUNodeLink *tex, GPUNodeLink *out, GPUNodeLink *fact, GPUNodeLink *facg,
@@ -308,16 +266,6 @@ void GPU_material_free(ListBase *gpumaterial)
BLI_freelistN(gpumaterial);
}
-bool GPU_lamp_override_visible(GPULamp *lamp, SceneRenderLayer *srl, Material *ma)
-{
- if (srl && srl->light_override)
- return BKE_group_object_exists(srl->light_override, lamp->ob);
- else if (ma && ma->group)
- return BKE_group_object_exists(ma->group, lamp->ob);
- else
- return true;
-}
-
void GPU_material_bind(
GPUMaterial *material, int oblay, int viewlay, double time, int mipmap,
float viewmat[4][4], float viewinv[4][4], float camerafactors[4], bool scenelock)
@@ -2222,391 +2170,6 @@ void GPU_materials_free(void)
/* Lamps and shadow buffers */
-static void gpu_lamp_calc_winmat(GPULamp *lamp)
-{
- float temp, angle, pixsize, wsize;
-
- if (lamp->type == LA_SUN) {
- wsize = lamp->la->shadow_frustum_size;
- orthographic_m4(lamp->winmat, -wsize, wsize, -wsize, wsize, lamp->d, lamp->clipend);
- }
- else if (lamp->type == LA_SPOT) {
- angle = saacos(lamp->spotsi);
- temp = 0.5f * lamp->size * cosf(angle) / sinf(angle);
- pixsize = lamp->d / temp;
- wsize = pixsize * 0.5f * lamp->size;
- /* compute shadows according to X and Y scaling factors */
- perspective_m4(
- lamp->winmat,
- -wsize * lamp->spotvec[0], wsize * lamp->spotvec[0],
- -wsize * lamp->spotvec[1], wsize * lamp->spotvec[1],
- lamp->d, lamp->clipend);
- }
-}
-
-void GPU_lamp_update(GPULamp *lamp, int lay, int hide, float obmat[4][4])
-{
- float mat[4][4];
- float obmat_scale[3];
-
- lamp->lay = lay;
- lamp->hide = hide;
-
- normalize_m4_m4_ex(mat, obmat, obmat_scale);
-
- copy_v3_v3(lamp->vec, mat[2]);
- copy_v3_v3(lamp->co, mat[3]);
- copy_m4_m4(lamp->obmat, mat);
- invert_m4_m4(lamp->imat, mat);
-
- if (lamp->type == LA_SPOT) {
- /* update spotlamp scale on X and Y axis */
- lamp->spotvec[0] = obmat_scale[0] / obmat_scale[2];
- lamp->spotvec[1] = obmat_scale[1] / obmat_scale[2];
- }
-
- if (GPU_lamp_has_shadow_buffer(lamp)) {
- /* makeshadowbuf */
- gpu_lamp_calc_winmat(lamp);
- }
-}
-
-void GPU_lamp_update_colors(GPULamp *lamp, float r, float g, float b, float energy)
-{
- lamp->energy = energy;
- if (lamp->mode & LA_NEG) lamp->energy = -lamp->energy;
-
- lamp->col[0] = r;
- lamp->col[1] = g;
- lamp->col[2] = b;
-}
-
-void GPU_lamp_update_distance(GPULamp *lamp, float distance, float att1, float att2,
- float coeff_const, float coeff_lin, float coeff_quad)
-{
- lamp->dist = distance;
- lamp->att1 = att1;
- lamp->att2 = att2;
- lamp->coeff_const = coeff_const;
- lamp->coeff_lin = coeff_lin;
- lamp->coeff_quad = coeff_quad;
-}
-
-void GPU_lamp_update_spot(GPULamp *lamp, float spotsize, float spotblend)
-{
- lamp->spotsi = cosf(spotsize * 0.5f);
- lamp->spotbl = (1.0f - lamp->spotsi) * spotblend;
-}
-
-static void gpu_lamp_from_blender(Scene *scene, Object *ob, Object *par, Lamp *la, GPULamp *lamp)
-{
- lamp->scene = scene;
- lamp->ob = ob;
- lamp->par = par;
- lamp->la = la;
-
- /* add_render_lamp */
- lamp->mode = la->mode;
- lamp->type = la->type;
-
- lamp->energy = la->energy;
- if (lamp->mode & LA_NEG) lamp->energy = -lamp->energy;
-
- lamp->col[0] = la->r;
- lamp->col[1] = la->g;
- lamp->col[2] = la->b;
-
- GPU_lamp_update(lamp, ob->lay, (ob->restrictflag & OB_RESTRICT_RENDER), ob->obmat);
-
- lamp->spotsi = la->spotsize;
- if (lamp->mode & LA_HALO)
- if (lamp->spotsi > DEG2RADF(170.0f))
- lamp->spotsi = DEG2RADF(170.0f);
- lamp->spotsi = cosf(lamp->spotsi * 0.5f);
- lamp->spotbl = (1.0f - lamp->spotsi) * la->spotblend;
- lamp->k = la->k;
-
- lamp->dist = la->dist;
- lamp->falloff_type = la->falloff_type;
- lamp->att1 = la->att1;
- lamp->att2 = la->att2;
- lamp->coeff_const = la->coeff_const;
- lamp->coeff_lin = la->coeff_lin;
- lamp->coeff_quad = la->coeff_quad;
- lamp->curfalloff = la->curfalloff;
-
- /* initshadowbuf */
- lamp->bias = 0.02f * la->bias;
- lamp->size = la->bufsize;
- lamp->d = la->clipsta;
- lamp->clipend = la->clipend;
-
- /* arbitrary correction for the fact we do no soft transition */
- lamp->bias *= 0.25f;
-}
-
-static void gpu_lamp_shadow_free(GPULamp *lamp)
-{
- if (lamp->tex) {
- GPU_texture_free(lamp->tex);
- lamp->tex = NULL;
- }
- if (lamp->depthtex) {
- GPU_texture_free(lamp->depthtex);
- lamp->depthtex = NULL;
- }
- if (lamp->fb) {
- GPU_framebuffer_free(lamp->fb);
- lamp->fb = NULL;
- }
- if (lamp->blurtex) {
- GPU_texture_free(lamp->blurtex);
- lamp->blurtex = NULL;
- }
- if (lamp->blurfb) {
- GPU_framebuffer_free(lamp->blurfb);
- lamp->blurfb = NULL;
- }
-}
-
-static GPUTexture *gpu_lamp_create_vsm_shadow_map(int size)
-{
- return GPU_texture_create_2D_custom(size, size, 2, GPU_RG32F, NULL, NULL);
-}
-
-GPULamp *GPU_lamp_from_blender(Scene *scene, Object *ob, Object *par)
-{
- Lamp *la;
- GPULamp *lamp;
- LinkData *link;
-
- for (link = ob->gpulamp.first; link; link = link->next) {
- lamp = (GPULamp *)link->data;
-
- if (lamp->par == par && lamp->scene == scene)
- return link->data;
- }
-
- lamp = MEM_callocN(sizeof(GPULamp), "GPULamp");
-
- link = MEM_callocN(sizeof(LinkData), "GPULampLink");
- link->data = lamp;
- BLI_addtail(&ob->gpulamp, link);
-
- la = ob->data;
- gpu_lamp_from_blender(scene, ob, par, la, lamp);
-
- if ((la->type == LA_SPOT && (la->mode & (LA_SHAD_BUF | LA_SHAD_RAY))) ||
- (la->type == LA_SUN && (la->mode & LA_SHAD_RAY)))
- {
- /* opengl */
- lamp->fb = GPU_framebuffer_create();
- if (!lamp->fb) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
-
- if (lamp->la->shadowmap_type == LA_SHADMAP_VARIANCE) {
- /* Shadow depth map */
- lamp->depthtex = GPU_texture_create_depth(lamp->size, lamp->size, NULL);
- if (!lamp->depthtex) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
-
- if (!GPU_framebuffer_texture_attach(lamp->fb, lamp->depthtex, 0)) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
-
- /* Shadow color map */
- lamp->tex = gpu_lamp_create_vsm_shadow_map(lamp->size);
- if (!lamp->tex) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
-
- if (!GPU_framebuffer_texture_attach(lamp->fb, lamp->tex, 0)) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
-
- if (!GPU_framebuffer_check_valid(lamp->fb, NULL)) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
-
- /* FBO and texture for blurring */
- lamp->blurfb = GPU_framebuffer_create();
- if (!lamp->blurfb) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
-
- lamp->blurtex = gpu_lamp_create_vsm_shadow_map(lamp->size * 0.5);
- if (!lamp->blurtex) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
-
- if (!GPU_framebuffer_texture_attach(lamp->blurfb, lamp->blurtex, 0)) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
-
- /* we need to properly bind to test for completeness */
- GPU_texture_bind_as_framebuffer(lamp->blurtex);
-
- if (!GPU_framebuffer_check_valid(lamp->blurfb, NULL)) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
-
- GPU_framebuffer_texture_unbind(lamp->blurfb, lamp->blurtex);
- }
- else {
- lamp->tex = GPU_texture_create_depth(lamp->size, lamp->size, NULL);
- if (!lamp->tex) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
-
- if (!GPU_framebuffer_texture_attach(lamp->fb, lamp->tex, 0)) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
-
- if (!GPU_framebuffer_check_valid(lamp->fb, NULL)) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
- }
-
- GPU_framebuffer_restore();
-
- lamp->shadow_color[0] = la->shdwr;
- lamp->shadow_color[1] = la->shdwg;
- lamp->shadow_color[2] = la->shdwb;
- }
- else {
- lamp->shadow_color[0] = 1.0;
- lamp->shadow_color[1] = 1.0;
- lamp->shadow_color[2] = 1.0;
- }
-
- return lamp;
-}
-
-void GPU_lamp_free(Object *ob)
-{
- GPULamp *lamp;
- LinkData *link;
- LinkData *nlink;
- Material *ma;
-
- for (link = ob->gpulamp.first; link; link = link->next) {
- lamp = link->data;
-
- while (lamp->materials.first) {
- nlink = lamp->materials.first;
- ma = nlink->data;
- BLI_freelinkN(&lamp->materials, nlink);
-
- if (ma->gpumaterial.first)
- GPU_material_free(&ma->gpumaterial);
- }
-
- gpu_lamp_shadow_free(lamp);
-
- MEM_freeN(lamp);
- }
-
- BLI_freelistN(&ob->gpulamp);
-}
-
-bool GPU_lamp_has_shadow_buffer(GPULamp *lamp)
-{
- return (!(lamp->scene->gm.flag & GAME_GLSL_NO_SHADOWS) &&
- !(lamp->scene->gm.flag & GAME_GLSL_NO_LIGHTS) &&
- lamp->tex && lamp->fb);
-}
-
-void GPU_lamp_update_buffer_mats(GPULamp *lamp)
-{
- float rangemat[4][4], persmat[4][4];
-
- /* initshadowbuf */
- invert_m4_m4(lamp->viewmat, lamp->obmat);
- normalize_v3(lamp->viewmat[0]);
- normalize_v3(lamp->viewmat[1]);
- normalize_v3(lamp->viewmat[2]);
-
- /* makeshadowbuf */
- mul_m4_m4m4(persmat, lamp->winmat, lamp->viewmat);
-
- /* opengl depth buffer is range 0.0..1.0 instead of -1.0..1.0 in blender */
- unit_m4(rangemat);
- rangemat[0][0] = 0.5f;
- rangemat[1][1] = 0.5f;
- rangemat[2][2] = 0.5f;
- rangemat[3][0] = 0.5f;
- rangemat[3][1] = 0.5f;
- rangemat[3][2] = 0.5f;
-
- mul_m4_m4m4(lamp->persmat, rangemat, persmat);
-}
-
-void GPU_lamp_shadow_buffer_bind(GPULamp *lamp, float viewmat[4][4], int *winsize, float winmat[4][4])
-{
- GPU_lamp_update_buffer_mats(lamp);
-
- /* opengl */
- glDisable(GL_SCISSOR_TEST);
- GPU_texture_bind_as_framebuffer(lamp->tex);
- if (lamp->la->shadowmap_type == LA_SHADMAP_VARIANCE)
- GPU_shader_bind(GPU_shader_get_builtin_shader(GPU_SHADER_VSM_STORE));
-
- /* set matrices */
- copy_m4_m4(viewmat, lamp->viewmat);
- copy_m4_m4(winmat, lamp->winmat);
- *winsize = lamp->size;
-}
-
-void GPU_lamp_shadow_buffer_unbind(GPULamp *lamp)
-{
- if (lamp->la->shadowmap_type == LA_SHADMAP_VARIANCE) {
- GPU_shader_unbind();
- GPU_framebuffer_blur(lamp->fb, lamp->tex, lamp->blurfb, lamp->blurtex);
- }
-
- GPU_framebuffer_texture_unbind(lamp->fb, lamp->tex);
- GPU_framebuffer_restore();
- glEnable(GL_SCISSOR_TEST);
-}
-
-int GPU_lamp_shadow_buffer_type(GPULamp *lamp)
-{
- return lamp->la->shadowmap_type;
-}
-
-int GPU_lamp_shadow_bind_code(GPULamp *lamp)
-{
- return lamp->tex ? GPU_texture_opengl_bindcode(lamp->tex) : -1;
-}
-
-float *GPU_lamp_dynpersmat(GPULamp *lamp)
-{
- return &lamp->dynpersmat[0][0];
-}
-
-int GPU_lamp_shadow_layer(GPULamp *lamp)
-{
- if (lamp->fb && lamp->tex && (lamp->mode & (LA_LAYER | LA_LAYER_SHADOW)))
- return lamp->lay;
- else
- return -1;
-}
-
GPUNodeLink *GPU_lamp_get_data(
GPUMaterial *mat, GPULamp *lamp,
GPUNodeLink **r_col, GPUNodeLink **r_lv, GPUNodeLink **r_dist, GPUNodeLink **r_shadow, GPUNodeLink **r_energy)
diff --git a/source/blender/nodes/shader/node_shader_util.h b/source/blender/nodes/shader/node_shader_util.h
index 4cb39e0f13b..79c58cb5715 100644
--- a/source/blender/nodes/shader/node_shader_util.h
+++ b/source/blender/nodes/shader/node_shader_util.h
@@ -76,6 +76,7 @@
#include "RE_pipeline.h"
#include "RE_shader_ext.h"
+#include "GPU_lamp.h"
#include "GPU_material.h"
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLLight.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLLight.cpp
index fff988a07c5..d3bd7f74106 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLLight.cpp
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLLight.cpp
@@ -43,6 +43,7 @@
#include "DNA_lamp_types.h"
#include "DNA_scene_types.h"
+#include "GPU_lamp.h"
#include "GPU_material.h"
RAS_OpenGLLight::RAS_OpenGLLight(RAS_OpenGLRasterizer *ras)