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_extensions.h18
-rw-r--r--source/blender/gpu/GPU_material.h5
-rw-r--r--source/blender/gpu/SConscript3
-rw-r--r--source/blender/gpu/intern/gpu_buffers.c92
-rw-r--r--source/blender/gpu/intern/gpu_codegen.c16
-rw-r--r--source/blender/gpu/intern/gpu_compositing.c13
-rw-r--r--source/blender/gpu/intern/gpu_debug.c44
-rw-r--r--source/blender/gpu/intern/gpu_draw.c14
-rw-r--r--source/blender/gpu/intern/gpu_extensions.c293
-rw-r--r--source/blender/gpu/intern/gpu_init_exit.c2
-rw-r--r--source/blender/gpu/intern/gpu_material.c40
-rw-r--r--source/blender/gpu/shaders/gpu_shader_material.glsl23
12 files changed, 420 insertions, 143 deletions
diff --git a/source/blender/gpu/GPU_extensions.h b/source/blender/gpu/GPU_extensions.h
index f3927ba960b..685ae59c47b 100644
--- a/source/blender/gpu/GPU_extensions.h
+++ b/source/blender/gpu/GPU_extensions.h
@@ -130,6 +130,8 @@ GPUTexture *GPU_texture_create_depth(int w, int h, char err_out[256]);
GPUTexture *GPU_texture_create_vsm_shadow_map(int size, char err_out[256]);
GPUTexture *GPU_texture_create_2D_procedural(int w, int h, const float *pixels, bool repeat, char err_out[256]);
GPUTexture *GPU_texture_create_1D_procedural(int w, const float *pixels, char err_out[256]);
+GPUTexture *GPU_texture_create_2D_multisample(int w, int h, const float *pixels, GPUHDRType hdr, int samples, char err_out[256]);
+GPUTexture *GPU_texture_create_depth_multisample(int w, int h, int samples, char err_out[256]);
GPUTexture *GPU_texture_from_blender(struct Image *ima,
struct ImageUser *iuser, bool is_data, double time, int mipmap);
GPUTexture *GPU_texture_from_preview(struct PreviewImage *prv, int mipmap);
@@ -179,13 +181,14 @@ void GPU_framebuffer_blur(GPUFrameBuffer *fb, GPUTexture *tex, GPUFrameBuffer *b
* - wrapper around framebuffer and texture for simple offscreen drawing
* - changes size if graphics card can't support it */
-GPUOffScreen *GPU_offscreen_create(int width, int height, char err_out[256]);
+GPUOffScreen *GPU_offscreen_create(int width, int height, int samples, char err_out[256]);
void GPU_offscreen_free(GPUOffScreen *ofs);
void GPU_offscreen_bind(GPUOffScreen *ofs, bool save);
void GPU_offscreen_unbind(GPUOffScreen *ofs, bool restore);
void GPU_offscreen_read_pixels(GPUOffScreen *ofs, int type, void *pixels);
int GPU_offscreen_width(const GPUOffScreen *ofs);
int GPU_offscreen_height(const GPUOffScreen *ofs);
+int GPU_offscreen_color_texture(const GPUOffScreen *ofs);
/* Builtin/Non-generated shaders */
typedef enum GPUProgramType {
@@ -204,6 +207,19 @@ void GPU_program_unbind(GPUProgram *);
* - must call texture bind before setting a texture as uniform! */
GPUShader *GPU_shader_create(const char *vertexcode, const char *fragcode, const char *geocode, const char *libcode, const char *defines, int input, int output, int number);
+enum {
+ GPU_SHADER_FLAGS_NONE = 0,
+ GPU_SHADER_FLAGS_SPECIAL_OPENSUBDIV = (1 << 0),
+};
+GPUShader *GPU_shader_create_ex(const char *vertexcode,
+ const char *fragcode,
+ const char *geocode,
+ const char *libcode,
+ const char *defines,
+ int input,
+ int output,
+ int number,
+ const int flags);
void GPU_shader_free(GPUShader *shader);
void GPU_shader_bind(GPUShader *shader);
diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h
index dd08ed83e5a..25a4f33b526 100644
--- a/source/blender/gpu/GPU_material.h
+++ b/source/blender/gpu/GPU_material.h
@@ -160,6 +160,7 @@ typedef enum GPUDynamicType {
GPU_DYNAMIC_LAMP_ATT2 = 9 | GPU_DYNAMIC_GROUP_LAMP,
GPU_DYNAMIC_LAMP_SPOTSIZE = 10 | GPU_DYNAMIC_GROUP_LAMP,
GPU_DYNAMIC_LAMP_SPOTBLEND = 11 | GPU_DYNAMIC_GROUP_LAMP,
+ GPU_DYNAMIC_LAMP_SPOTSCALE = 12 | GPU_DYNAMIC_GROUP_LAMP,
GPU_DYNAMIC_SAMPLER_2DBUFFER = 1 | GPU_DYNAMIC_GROUP_SAMPLER,
GPU_DYNAMIC_SAMPLER_2DIMAGE = 2 | GPU_DYNAMIC_GROUP_SAMPLER,
@@ -314,13 +315,13 @@ void GPU_mist_update_values(int type, float start, float dist, float inten, floa
void GPU_horizon_update_color(float color[3]);
void GPU_ambient_update_color(float color[3]);
-typedef struct GPUParticleInfo
+struct GPUParticleInfo
{
float scalprops[4];
float location[3];
float velocity[3];
float angular_velocity[3];
-} GPUParticleInfo;
+};
#ifdef WITH_OPENSUBDIV
struct DerivedMesh;
diff --git a/source/blender/gpu/SConscript b/source/blender/gpu/SConscript
index 880a6d14e26..d27d5b09b56 100644
--- a/source/blender/gpu/SConscript
+++ b/source/blender/gpu/SConscript
@@ -30,7 +30,8 @@ Import ('env')
sources = env.Glob('intern/*.c')
sources += env.Glob('shaders/*.c')
-defs = env['BF_GL_DEFINITIONS']
+defs = []
+defs += env['BF_GL_DEFINITIONS']
incs = [
'.',
diff --git a/source/blender/gpu/intern/gpu_buffers.c b/source/blender/gpu/intern/gpu_buffers.c
index 2e1b866a160..b4617b9790e 100644
--- a/source/blender/gpu/intern/gpu_buffers.c
+++ b/source/blender/gpu/intern/gpu_buffers.c
@@ -95,8 +95,6 @@ const GPUBufferTypeSettings gpu_buffer_type_settings[] = {
{GL_ELEMENT_ARRAY_BUFFER_ARB, 4},
/* triangles, 1 point since we are allocating from tottriangle points, which account for all points */
{GL_ELEMENT_ARRAY_BUFFER_ARB, 1},
- /* fast triangles */
- {GL_ELEMENT_ARRAY_BUFFER_ARB, 1},
};
#define MAX_GPU_ATTRIB_DATA 32
@@ -1121,6 +1119,9 @@ struct GPU_PBVH_Buffers {
GPUBuffer *vert_buf, *index_buf, *index_buf_fast;
GLenum index_type;
+ int *baseelemarray;
+ void **baseindex;
+
/* mesh pointers in case buffer allocation fails */
const MPoly *mpoly;
const MLoop *mloop;
@@ -1607,26 +1608,26 @@ static GPUBuffer *gpu_get_grid_buffer(int gridsize, GLenum *index_type, unsigned
#define FILL_FAST_BUFFER(type_) \
{ \
- type_ *buffer; \
- buffers->index_buf_fast = GPU_buffer_alloc(sizeof(type_) * 6 * totgrid, false); \
- buffer = GPU_buffer_lock(buffers->index_buf_fast, GPU_BINDING_INDEX); \
- if (buffer) { \
- int i; \
- for (i = 0; i < totgrid; i++) { \
- int currentquad = i * 6; \
- buffer[currentquad] = i * gridsize * gridsize; \
- buffer[currentquad + 1] = i * gridsize * gridsize + gridsize - 1; \
- buffer[currentquad + 2] = (i + 1) * gridsize * gridsize - gridsize; \
- buffer[currentquad + 3] = (i + 1) * gridsize * gridsize - 1; \
- buffer[currentquad + 4] = i * gridsize * gridsize + gridsize - 1; \
- buffer[currentquad + 5] = (i + 1) * gridsize * gridsize - gridsize; \
- } \
- GPU_buffer_unlock(buffers->index_buf_fast, GPU_BINDING_INDEX); \
+ type_ *buffer; \
+ buffers->index_buf_fast = GPU_buffer_alloc(sizeof(type_) * 6 * totgrid, false); \
+ buffer = GPU_buffer_lock(buffers->index_buf_fast, GPU_BINDING_INDEX); \
+ if (buffer) { \
+ int i; \
+ for (i = 0; i < totgrid; i++) { \
+ int currentquad = i * 6; \
+ buffer[currentquad] = i * gridsize * gridsize + gridsize - 1; \
+ buffer[currentquad + 1] = i * gridsize * gridsize; \
+ buffer[currentquad + 2] = (i + 1) * gridsize * gridsize - gridsize; \
+ buffer[currentquad + 3] = (i + 1) * gridsize * gridsize - 1; \
+ buffer[currentquad + 4] = i * gridsize * gridsize + gridsize - 1; \
+ buffer[currentquad + 5] = (i + 1) * gridsize * gridsize - gridsize; \
+ } \
+ GPU_buffer_unlock(buffers->index_buf_fast, GPU_BINDING_INDEX); \
} \
else { \
- GPU_buffer_free(buffers->index_buf_fast); \
- buffers->index_buf_fast = NULL; \
- } \
+ GPU_buffer_free(buffers->index_buf_fast); \
+ buffers->index_buf_fast = NULL; \
+ } \
} (void)0
GPU_PBVH_Buffers *GPU_build_grid_pbvh_buffers(int *grid_indices, int totgrid,
@@ -1681,6 +1682,18 @@ GPU_PBVH_Buffers *GPU_build_grid_pbvh_buffers(int *grid_indices, int totgrid,
if (buffers->index_buf)
buffers->vert_buf = GPU_buffer_alloc(sizeof(VertexBufferFormat) * totgrid * key->grid_area, false);
+ if (GLEW_ARB_draw_elements_base_vertex) {
+ int i;
+ buffers->baseelemarray = MEM_mallocN(sizeof(int) * totgrid * 2, "GPU_PBVH_Buffers.baseelemarray");
+ buffers->baseindex = MEM_mallocN(sizeof(void *) * totgrid, "GPU_PBVH_Buffers.baseindex");
+ for (i = 0; i < totgrid; i++) {
+ buffers->baseelemarray[i] = buffers->tot_quad * 6;
+ buffers->baseelemarray[i + totgrid] = i * key->grid_area;
+ buffers->baseindex[i] = buffers->index_buf && !buffers->index_buf->use_vbo ?
+ buffers->index_buf->pointer : NULL;
+ }
+ }
+
return buffers;
}
@@ -2012,21 +2025,40 @@ void GPU_draw_pbvh_buffers(GPU_PBVH_Buffers *buffers, DMSetMaterial setMaterial,
if (buffers->tot_quad) {
const char *offset = base;
- int i, last = buffers->has_hidden ? 1 : buffers->totgrid;
- for (i = 0; i < last; i++) {
+ const bool drawall = !(buffers->has_hidden || do_fast);
+
+ if (GLEW_ARB_draw_elements_base_vertex && drawall) {
+
glVertexPointer(3, GL_FLOAT, sizeof(VertexBufferFormat),
offset + offsetof(VertexBufferFormat, co));
glNormalPointer(GL_SHORT, sizeof(VertexBufferFormat),
offset + offsetof(VertexBufferFormat, no));
glColorPointer(3, GL_UNSIGNED_BYTE, sizeof(VertexBufferFormat),
offset + offsetof(VertexBufferFormat, color));
-
- if (do_fast)
- glDrawElements(GL_TRIANGLES, buffers->totgrid * 6, buffers->index_type, index_base);
- else
- glDrawElements(GL_TRIANGLES, buffers->tot_quad * 6, buffers->index_type, index_base);
- offset += buffers->gridkey.grid_area * sizeof(VertexBufferFormat);
+ glMultiDrawElementsBaseVertex(GL_TRIANGLES, buffers->baseelemarray, buffers->index_type,
+ (const void * const *)buffers->baseindex,
+ buffers->totgrid, &buffers->baseelemarray[buffers->totgrid]);
+ }
+ else {
+ int i, last = drawall ? buffers->totgrid : 1;
+
+ /* we could optimize this to one draw call, but it would need more memory */
+ for (i = 0; i < last; i++) {
+ glVertexPointer(3, GL_FLOAT, sizeof(VertexBufferFormat),
+ offset + offsetof(VertexBufferFormat, co));
+ glNormalPointer(GL_SHORT, sizeof(VertexBufferFormat),
+ offset + offsetof(VertexBufferFormat, no));
+ glColorPointer(3, GL_UNSIGNED_BYTE, sizeof(VertexBufferFormat),
+ offset + offsetof(VertexBufferFormat, color));
+
+ if (do_fast)
+ glDrawElements(GL_TRIANGLES, buffers->totgrid * 6, buffers->index_type, index_base);
+ else
+ glDrawElements(GL_TRIANGLES, buffers->tot_quad * 6, buffers->index_type, index_base);
+
+ offset += buffers->gridkey.grid_area * sizeof(VertexBufferFormat);
+ }
}
}
else if (buffers->tot_tri) {
@@ -2112,6 +2144,10 @@ void GPU_free_pbvh_buffers(GPU_PBVH_Buffers *buffers)
GPU_buffer_free(buffers->index_buf);
if (buffers->index_buf_fast)
GPU_buffer_free(buffers->index_buf_fast);
+ if (buffers->baseelemarray)
+ MEM_freeN(buffers->baseelemarray);
+ if (buffers->baseindex)
+ MEM_freeN(buffers->baseindex);
MEM_freeN(buffers);
}
diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c
index 68b9e3845f7..496302bb44e 100644
--- a/source/blender/gpu/intern/gpu_codegen.c
+++ b/source/blender/gpu/intern/gpu_codegen.c
@@ -718,7 +718,7 @@ static char *code_generate_vertex(ListBase *nodes, const GPUMatType type)
GPUNode *node;
GPUInput *input;
char *code;
- char *vertcode;
+ char *vertcode = NULL;
for (node = nodes->first; node; node = node->next) {
for (input = node->inputs.first; input; input = input->next) {
@@ -839,6 +839,8 @@ static char *code_generate_geometry(ListBase *nodes, bool use_opensubdiv)
BLI_dynstr_append(ds, datatoc_gpu_shader_geometry_glsl);
/* Generate varying assignments. */
+ /* TODO(sergey): Disabled for now, needs revisit. */
+#if 0
for (node = nodes->first; node; node = node->next) {
for (input = node->inputs.first; input; input = input->next) {
if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) {
@@ -852,6 +854,7 @@ static char *code_generate_geometry(ListBase *nodes, bool use_opensubdiv)
}
}
}
+#endif
BLI_dynstr_append(ds, "}\n\n");
code = BLI_dynstr_get_cstring(ds);
@@ -1612,7 +1615,16 @@ GPUPass *GPU_generate_pass(ListBase *nodes, GPUNodeLink *outlink,
fragmentcode = code_generate_fragment(nodes, outlink->output);
vertexcode = code_generate_vertex(nodes, type);
geometrycode = code_generate_geometry(nodes, use_opensubdiv);
- shader = GPU_shader_create(vertexcode, fragmentcode, geometrycode, glsl_material_library, NULL, 0, 0, 0);
+ shader = GPU_shader_create_ex(vertexcode,
+ fragmentcode,
+ geometrycode,
+ glsl_material_library,
+ NULL,
+ 0,
+ 0,
+ 0,
+ use_opensubdiv ? GPU_SHADER_FLAGS_SPECIAL_OPENSUBDIV
+ : GPU_SHADER_FLAGS_NONE);
/* failed? */
if (!shader) {
diff --git a/source/blender/gpu/intern/gpu_compositing.c b/source/blender/gpu/intern/gpu_compositing.c
index 2bafee0fb52..da5db73d382 100644
--- a/source/blender/gpu/intern/gpu_compositing.c
+++ b/source/blender/gpu/intern/gpu_compositing.c
@@ -306,6 +306,9 @@ bool GPU_fx_compositor_initialize_passes(
fx->effects = 0;
+ if (!GPU_non_power_of_two_support() || !GLEW_EXT_framebuffer_object || !GLEW_ARB_fragment_shader)
+ return false;
+
if (!fx_settings) {
cleanup_fx_gl_data(fx, true);
return false;
@@ -340,16 +343,18 @@ bool GPU_fx_compositor_initialize_passes(
if (fx_flag & GPU_FX_FLAG_SSAO)
num_passes++;
- if (!fx->gbuffer)
+ if (!fx->gbuffer) {
fx->gbuffer = GPU_framebuffer_create();
+ if (!fx->gbuffer) {
+ return false;
+ }
+ }
+
/* try creating the jitter texture */
if (!fx->jitter_buffer)
fx->jitter_buffer = create_jitter_texture();
- if (!fx->gbuffer)
- return false;
-
/* check if color buffers need recreation */
if (!fx->color_buffer || !fx->depth_buffer || w != fx->gbuffer_dim[0] || h != fx->gbuffer_dim[1]) {
cleanup_fx_gl_data(fx, false);
diff --git a/source/blender/gpu/intern/gpu_debug.c b/source/blender/gpu/intern/gpu_debug.c
index 15fe6edb2de..29b7ff11586 100644
--- a/source/blender/gpu/intern/gpu_debug.c
+++ b/source/blender/gpu/intern/gpu_debug.c
@@ -43,7 +43,7 @@
#define CASE_CODE_RETURN_STR(code) case code: return #code;
-static const char* gpu_gl_error_symbol(GLenum err)
+static const char *gpu_gl_error_symbol(GLenum err)
{
switch (err) {
CASE_CODE_RETURN_STR(GL_NO_ERROR)
@@ -81,8 +81,8 @@ static bool gpu_report_gl_errors(const char *file, int line, const char *str)
}
else {
/* glGetError should have cleared the error flag, so if we get the
- same flag twice that means glGetError itself probably triggered
- the error. This happens on Windows if the GL context is invalid.
+ * same flag twice that means glGetError itself probably triggered
+ * the error. This happens on Windows if the GL context is invalid.
*/
{
GLenum new_error = glGetError();
@@ -92,22 +92,18 @@ static bool gpu_report_gl_errors(const char *file, int line, const char *str)
}
}
- fprintf(
- stderr,
- "%s(%d): ``%s'' -> GL Error (0x%04X - %s): %s\n",
- file,
- line,
- str,
- gl_error,
- gpu_gl_error_symbol(gl_error),
- gpuErrorString(gl_error));
+ fprintf(stderr,
+ "%s:%d: ``%s'' -> GL Error (0x%04X - %s): %s\n",
+ file, line, str, gl_error,
+ gpu_gl_error_symbol(gl_error),
+ gpuErrorString(gl_error));
return false;
}
}
-const char* gpuErrorString(GLenum err)
+const char *gpuErrorString(GLenum err)
{
switch (err) {
case GL_NO_ERROR:
@@ -163,9 +159,10 @@ const char* gpuErrorString(GLenum err)
#endif
-static void APIENTRY gpu_debug_proc(GLenum source, GLenum type, GLuint UNUSED(id),
- GLenum UNUSED(severity), GLsizei UNUSED(length),
- const GLchar *message, GLvoid *UNUSED(userParm))
+static void APIENTRY gpu_debug_proc(
+ GLenum source, GLenum type, GLuint UNUSED(id),
+ GLenum UNUSED(severity), GLsizei UNUSED(length),
+ const GLchar *message, const GLvoid *UNUSED(userParm))
{
if (source == GL_DEBUG_SOURCE_API && type == GL_DEBUG_TYPE_ERROR) {
fprintf(stderr, "GL: %s\n", message);
@@ -179,9 +176,10 @@ static void APIENTRY gpu_debug_proc(GLenum source, GLenum type, GLuint UNUSED(id
#ifndef GLEW_ES_ONLY
-static void APIENTRY gpu_debug_proc_amd(GLuint UNUSED(id), GLenum UNUSED(category),
- GLenum UNUSED(severity), GLsizei UNUSED(length),
- const GLchar *message, GLvoid *UNUSED(userParm))
+static void APIENTRY gpu_debug_proc_amd(
+ GLuint UNUSED(id), GLenum UNUSED(category),
+ GLenum UNUSED(severity), GLsizei UNUSED(length),
+ const GLchar *message, GLvoid *UNUSED(userParm))
{
fprintf(stderr, "GL: %s\n", message);
}
@@ -206,9 +204,9 @@ void gpu_debug_init(void)
if (GLEW_KHR_debug) {
#ifndef GLEW_ES_ONLY
- glDebugMessageCallback(gpu_debug_proc, mxGetCurrentContext());
- glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, NULL, GL_TRUE);
- GPU_string_marker(sizeof(success), success);
+ glDebugMessageCallback(gpu_debug_proc, mxGetCurrentContext());
+ glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, NULL, GL_TRUE);
+ GPU_string_marker(sizeof(success), success);
#endif
return;
}
@@ -322,7 +320,7 @@ void GPU_print_error_debug(const char *str)
}
-void GPU_assert_no_gl_errors(const char* file, int line, const char* str)
+void GPU_assert_no_gl_errors(const char *file, int line, const char *str)
{
if (G.debug) {
GLboolean gl_ok = gpu_report_gl_errors(file, line, str);
diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c
index af8b2a0f806..bf7b8fbc386 100644
--- a/source/blender/gpu/intern/gpu_draw.c
+++ b/source/blender/gpu/intern/gpu_draw.c
@@ -1533,11 +1533,15 @@ void GPU_begin_object_materials(View3D *v3d, RegionView3D *rv3d, Scene *scene, O
#ifdef WITH_OPENSUBDIV
{
DerivedMesh *derivedFinal = NULL;
- Mesh *me = ob->data;
- BMEditMesh *em = me->edit_btmesh;
-
- if (em != NULL) {
- derivedFinal = em->derivedFinal;
+ if (ob->type == OB_MESH) {
+ Mesh *me = ob->data;
+ BMEditMesh *em = me->edit_btmesh;
+ if (em != NULL) {
+ derivedFinal = em->derivedFinal;
+ }
+ else {
+ derivedFinal = ob->derivedFinal;
+ }
}
else {
derivedFinal = ob->derivedFinal;
diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c
index ca9b4225faa..e1dff03d500 100644
--- a/source/blender/gpu/intern/gpu_extensions.c
+++ b/source/blender/gpu/intern/gpu_extensions.c
@@ -110,6 +110,7 @@ static struct GPUGlobal {
int glslsupport;
int extdisabled;
int colordepth;
+ int samples_color_texture_max;
int npotdisabled; /* ATI 3xx-5xx (and more) chipsets support NPoT partially (== not enough) */
int dlistsdisabled; /* Legacy ATI driver does not support display lists well */
GPUDeviceType device;
@@ -180,6 +181,10 @@ void gpu_extensions_init(void)
glGetIntegerv(GL_BLUE_BITS, &b);
GG.colordepth = r + g + b; /* assumes same depth for RGB */
+ if (GLEW_ARB_texture_multisample) {
+ glGetIntegerv(GL_MAX_COLOR_TEXTURE_SAMPLES , &GG.samples_color_texture_max);
+ }
+
vendor = (const char *)glGetString(GL_VENDOR);
renderer = (const char *)glGetString(GL_RENDERER);
version = (const char *)glGetString(GL_VERSION);
@@ -380,15 +385,18 @@ static void GPU_print_framebuffer_error(GLenum status, char err_out[256])
struct GPUTexture {
int w, h; /* width/height */
+ int w_orig, h_orig; /* width/height (before power of 2 is applied) */
int number; /* number for multitexture binding */
int refcount; /* reference count */
GLenum target; /* GL_TEXTURE_* */
+ GLenum target_base; /* same as target, (but no multisample) */
GLuint bindcode; /* opengl identifier for texture */
int fromblender; /* we got the texture from Blender */
GPUFrameBuffer *fb; /* GPUFramebuffer this texture is attached to */
int fb_attachment; /* slot the texture is attached to */
int depth; /* is a depth texture? if 3D how deep? */
+ int depth_orig; /* depth (before power of 2 is applied) */
};
static unsigned char *GPU_texture_convert_pixels(int length, const float *fpixels)
@@ -419,7 +427,8 @@ static void GPU_glTexSubImageEmpty(GLenum target, GLenum format, int x, int y, i
}
static GPUTexture *GPU_texture_create_nD(
- int w, int h, int n, const float *fpixels, int depth, GPUHDRType hdr_type, int components,
+ int w, int h, int n, const float *fpixels, int depth,
+ GPUHDRType hdr_type, int components, int samples,
char err_out[256])
{
GPUTexture *tex;
@@ -429,13 +438,18 @@ static GPUTexture *GPU_texture_create_nD(
if (depth && !GLEW_ARB_depth_texture)
return NULL;
+ if (samples) {
+ CLAMP_MAX(samples, GG.samples_color_texture_max);
+ }
+
tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture");
- tex->w = w;
- tex->h = h;
+ tex->w = tex->w_orig = w;
+ tex->h = tex->h_orig = h;
tex->number = -1;
tex->refcount = 1;
- tex->target = (n == 1)? GL_TEXTURE_1D: GL_TEXTURE_2D;
- tex->depth = depth;
+ tex->target = (n == 1) ? GL_TEXTURE_1D : (samples ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D);
+ tex->target_base = (n == 1) ? GL_TEXTURE_1D : GL_TEXTURE_2D;
+ tex->depth = tex->depth_orig = depth;
tex->fb_attachment = -1;
glGenTextures(1, &tex->bindcode);
@@ -521,8 +535,13 @@ static GPUTexture *GPU_texture_create_nD(
}
}
else {
- glTexImage2D(tex->target, 0, internalformat, tex->w, tex->h, 0,
- format, type, NULL);
+ if (samples) {
+ glTexImage2DMultisample(tex->target, samples, internalformat, tex->w, tex->h, true);
+ }
+ else {
+ glTexImage2D(tex->target, 0, internalformat, tex->w, tex->h, 0,
+ format, type, NULL);
+ }
if (fpixels) {
glTexSubImage2D(tex->target, 0, 0, 0, w, h,
@@ -539,23 +558,23 @@ static GPUTexture *GPU_texture_create_nD(
MEM_freeN(pixels);
if (depth) {
- glTexParameteri(tex->target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(tex->target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(tex->target, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE);
- glTexParameteri(tex->target, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);
- glTexParameteri(tex->target, GL_DEPTH_TEXTURE_MODE_ARB, GL_INTENSITY);
+ glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE);
+ glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);
+ glTexParameteri(tex->target_base, GL_DEPTH_TEXTURE_MODE_ARB, GL_INTENSITY);
}
else {
- glTexParameteri(tex->target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(tex->target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
- if (tex->target != GL_TEXTURE_1D) {
- glTexParameteri(tex->target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(tex->target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ if (tex->target_base != GL_TEXTURE_1D) {
+ glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
}
else
- glTexParameteri(tex->target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
return tex;
}
@@ -573,12 +592,13 @@ GPUTexture *GPU_texture_create_3D(int w, int h, int depth, int channels, const f
return NULL;
tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture");
- tex->w = w;
- tex->h = h;
- tex->depth = depth;
+ tex->w = tex->w_orig = w;
+ tex->h = tex->h_orig = h;
+ tex->depth = tex->depth_orig = depth;
tex->number = -1;
tex->refcount = 1;
tex->target = GL_TEXTURE_3D;
+ tex->target_base = GL_TEXTURE_3D;
glGenTextures(1, &tex->bindcode);
@@ -725,6 +745,7 @@ GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, bool is_data,
tex->number = -1;
tex->refcount = 1;
tex->target = GL_TEXTURE_2D;
+ tex->target_base = GL_TEXTURE_2D;
tex->fromblender = 1;
ima->gputexture= tex;
@@ -738,8 +759,8 @@ GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, bool is_data,
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &h);
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_BORDER, &border);
- tex->w = w - border;
- tex->h = h - border;
+ tex->w = tex->w_orig = w - border;
+ tex->h = tex->h_orig = h - border;
}
glBindTexture(GL_TEXTURE_2D, lastbindcode);
@@ -773,6 +794,7 @@ GPUTexture *GPU_texture_from_preview(PreviewImage *prv, int mipmap)
tex->number = -1;
tex->refcount = 1;
tex->target = GL_TEXTURE_2D;
+ tex->target_base = GL_TEXTURE_2D;
prv->gputexture[0] = tex;
@@ -784,8 +806,8 @@ GPUTexture *GPU_texture_from_preview(PreviewImage *prv, int mipmap)
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &w);
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &h);
- tex->w = w;
- tex->h = h;
+ tex->w = tex->w_orig = w;
+ tex->h = tex->h_orig = h;
}
glBindTexture(GL_TEXTURE_2D, lastbindcode);
@@ -796,7 +818,7 @@ GPUTexture *GPU_texture_from_preview(PreviewImage *prv, int mipmap)
GPUTexture *GPU_texture_create_1D(int w, const float *fpixels, char err_out[256])
{
- GPUTexture *tex = GPU_texture_create_nD(w, 1, 1, fpixels, 0, GPU_HDR_NONE, 4, err_out);
+ GPUTexture *tex = GPU_texture_create_nD(w, 1, 1, fpixels, 0, GPU_HDR_NONE, 4, 0, err_out);
if (tex)
GPU_texture_unbind(tex);
@@ -806,30 +828,48 @@ GPUTexture *GPU_texture_create_1D(int w, const float *fpixels, char err_out[256]
GPUTexture *GPU_texture_create_2D(int w, int h, const float *fpixels, GPUHDRType hdr, char err_out[256])
{
- GPUTexture *tex = GPU_texture_create_nD(w, h, 2, fpixels, 0, hdr, 4, err_out);
+ GPUTexture *tex = GPU_texture_create_nD(w, h, 2, fpixels, 0, hdr, 4, 0, err_out);
if (tex)
GPU_texture_unbind(tex);
return tex;
}
+GPUTexture *GPU_texture_create_2D_multisample(int w, int h, const float *fpixels, GPUHDRType hdr, int samples, char err_out[256])
+{
+ GPUTexture *tex = GPU_texture_create_nD(w, h, 2, fpixels, 0, hdr, 4, samples, err_out);
+
+ if (tex)
+ GPU_texture_unbind(tex);
+
+ return tex;
+}
GPUTexture *GPU_texture_create_depth(int w, int h, char err_out[256])
{
- GPUTexture *tex = GPU_texture_create_nD(w, h, 2, NULL, 1, GPU_HDR_NONE, 1, err_out);
+ GPUTexture *tex = GPU_texture_create_nD(w, h, 2, NULL, 1, GPU_HDR_NONE, 1, 0, err_out);
if (tex)
GPU_texture_unbind(tex);
return tex;
}
+GPUTexture *GPU_texture_create_depth_multisample(int w, int h, int samples, char err_out[256])
+{
+ GPUTexture *tex = GPU_texture_create_nD(w, h, 2, NULL, 1, GPU_HDR_NONE, 1, samples, err_out);
+
+ if (tex)
+ GPU_texture_unbind(tex);
+
+ return tex;
+}
/**
* A shadow map for VSM needs two components (depth and depth^2)
*/
GPUTexture *GPU_texture_create_vsm_shadow_map(int size, char err_out[256])
{
- GPUTexture *tex = GPU_texture_create_nD(size, size, 2, NULL, 0, GPU_HDR_FULL_FLOAT, 2, err_out);
+ GPUTexture *tex = GPU_texture_create_nD(size, size, 2, NULL, 0, GPU_HDR_FULL_FLOAT, 2, 0, err_out);
if (tex) {
/* Now we tweak some of the settings */
@@ -844,7 +884,7 @@ GPUTexture *GPU_texture_create_vsm_shadow_map(int size, char err_out[256])
GPUTexture *GPU_texture_create_2D_procedural(int w, int h, const float *pixels, bool repeat, char err_out[256])
{
- GPUTexture *tex = GPU_texture_create_nD(w, h, 2, pixels, 0, GPU_HDR_HALF_FLOAT, 2, err_out);
+ GPUTexture *tex = GPU_texture_create_nD(w, h, 2, pixels, 0, GPU_HDR_HALF_FLOAT, 2, 0, err_out);
if (tex) {
/* Now we tweak some of the settings */
@@ -863,7 +903,7 @@ GPUTexture *GPU_texture_create_2D_procedural(int w, int h, const float *pixels,
GPUTexture *GPU_texture_create_1D_procedural(int w, const float *pixels, char err_out[256])
{
- GPUTexture *tex = GPU_texture_create_nD(w, 0, 1, pixels, 0, GPU_HDR_HALF_FLOAT, 2, err_out);
+ GPUTexture *tex = GPU_texture_create_nD(w, 0, 1, pixels, 0, GPU_HDR_HALF_FLOAT, 2, 0, err_out);
if (tex) {
/* Now we tweak some of the settings */
@@ -963,7 +1003,7 @@ void GPU_texture_unbind(GPUTexture *tex)
arbnumber = (GLenum)((GLuint)GL_TEXTURE0_ARB + tex->number);
if (tex->number != 0) glActiveTextureARB(arbnumber);
glBindTexture(tex->target, 0);
- glDisable(tex->target);
+ glDisable(tex->target_base);
if (tex->number != 0) glActiveTextureARB(GL_TEXTURE0_ARB);
tex->number = -1;
@@ -1187,8 +1227,12 @@ void GPU_texture_bind_as_framebuffer(GPUTexture *tex)
glReadBuffer(GL_COLOR_ATTACHMENT0_EXT + tex->fb_attachment);
}
+ if (tex->target == GL_TEXTURE_2D_MULTISAMPLE) {
+ glEnable(GL_MULTISAMPLE_ARB);
+ }
+
/* push matrices and set default viewport and matrix */
- glViewport(0, 0, tex->w, tex->h);
+ glViewport(0, 0, tex->w_orig, tex->h_orig);
GG.currentfb = tex->fb->object;
glMatrixMode(GL_PROJECTION);
@@ -1226,7 +1270,7 @@ void GPU_framebuffer_slots_bind(GPUFrameBuffer *fb, int slot)
glReadBuffer(GL_COLOR_ATTACHMENT0_EXT + slot);
/* push matrices and set default viewport and matrix */
- glViewport(0, 0, fb->colortex[slot]->w, fb->colortex[slot]->h);
+ glViewport(0, 0, fb->colortex[slot]->w_orig, fb->colortex[slot]->h_orig);
GG.currentfb = fb->object;
glMatrixMode(GL_PROJECTION);
@@ -1256,7 +1300,7 @@ void GPU_framebuffer_bind_no_save(GPUFrameBuffer *fb, int slot)
glReadBuffer(GL_COLOR_ATTACHMENT0_EXT + slot);
/* push matrices and set default viewport and matrix */
- glViewport(0, 0, fb->colortex[slot]->w, fb->colortex[slot]->h);
+ glViewport(0, 0, fb->colortex[slot]->w_orig, fb->colortex[slot]->h_orig);
GG.currentfb = fb->object;
GG.currentfb = fb->object;
}
@@ -1316,8 +1360,8 @@ void GPU_framebuffer_restore(void)
void GPU_framebuffer_blur(GPUFrameBuffer *fb, GPUTexture *tex, GPUFrameBuffer *blurfb, GPUTexture *blurtex)
{
- const float scaleh[2] = {1.0f / GPU_texture_opengl_width(blurtex), 0.0f};
- const float scalev[2] = {0.0f, 1.0f / GPU_texture_opengl_height(tex)};
+ const float scaleh[2] = {1.0f / blurtex->w_orig, 0.0f};
+ const float scalev[2] = {0.0f, 1.0f / tex->h_orig};
GPUShader *blur_shader = GPU_shader_get_builtin_shader(GPU_SHADER_SEP_GAUSSIAN_BLUR);
int scale_uniform, texture_source_uniform;
@@ -1341,7 +1385,7 @@ void GPU_framebuffer_blur(GPUFrameBuffer *fb, GPUTexture *tex, GPUFrameBuffer *b
GPU_shader_bind(blur_shader);
GPU_shader_uniform_vector(blur_shader, scale_uniform, 2, 1, scaleh);
GPU_shader_uniform_texture(blur_shader, texture_source_uniform, tex);
- glViewport(0, 0, GPU_texture_opengl_width(blurtex), GPU_texture_opengl_height(blurtex));
+ glViewport(0, 0, blurtex->w_orig, blurtex->h_orig);
/* Peparing to draw quad */
glMatrixMode(GL_MODELVIEW);
@@ -1370,7 +1414,7 @@ void GPU_framebuffer_blur(GPUFrameBuffer *fb, GPUTexture *tex, GPUFrameBuffer *b
GG.currentfb = fb->object;
- glViewport(0, 0, GPU_texture_opengl_width(tex), GPU_texture_opengl_height(tex));
+ glViewport(0, 0, tex->w_orig, tex->h_orig);
GPU_shader_uniform_vector(blur_shader, scale_uniform, 2, 1, scalev);
GPU_shader_uniform_texture(blur_shader, texture_source_uniform, blurtex);
GPU_texture_bind(blurtex, 0);
@@ -1393,7 +1437,7 @@ struct GPUOffScreen {
GPUTexture *depth;
};
-GPUOffScreen *GPU_offscreen_create(int width, int height, char err_out[256])
+GPUOffScreen *GPU_offscreen_create(int width, int height, int samples, char err_out[256])
{
GPUOffScreen *ofs;
@@ -1405,7 +1449,22 @@ GPUOffScreen *GPU_offscreen_create(int width, int height, char err_out[256])
return NULL;
}
- ofs->depth = GPU_texture_create_depth(width, height, err_out);
+ if (samples) {
+ if (!GLEW_EXT_framebuffer_multisample ||
+ !GLEW_ARB_texture_multisample ||
+ /* Only needed for GPU_offscreen_read_pixels.
+ * We could add an arg if we intend to use multi-samle
+ * offscreen buffers w/o reading their pixels */
+ !GLEW_EXT_framebuffer_blit ||
+ /* This is required when blitting from a multi-sampled buffers,
+ * even though we're not scaling. */
+ !GLEW_EXT_framebuffer_multisample_blit_scaled)
+ {
+ samples = 0;
+ }
+ }
+
+ ofs->depth = GPU_texture_create_depth_multisample(width, height, samples, err_out);
if (!ofs->depth) {
GPU_offscreen_free(ofs);
return NULL;
@@ -1416,7 +1475,7 @@ GPUOffScreen *GPU_offscreen_create(int width, int height, char err_out[256])
return NULL;
}
- ofs->color = GPU_texture_create_2D(width, height, NULL, GPU_HDR_NONE, err_out);
+ ofs->color = GPU_texture_create_2D_multisample(width, height, NULL, GPU_HDR_NONE, samples, err_out);
if (!ofs->color) {
GPU_offscreen_free(ofs);
return NULL;
@@ -1470,17 +1529,96 @@ void GPU_offscreen_unbind(GPUOffScreen *ofs, bool restore)
void GPU_offscreen_read_pixels(GPUOffScreen *ofs, int type, void *pixels)
{
- glReadPixels(0, 0, ofs->color->w, ofs->color->h, GL_RGBA, type, pixels);
+ const int w = ofs->color->w_orig;
+ const int h = ofs->color->h_orig;
+
+ if (ofs->color->target == GL_TEXTURE_2D_MULTISAMPLE) {
+ /* For a multi-sample texture,
+ * we need to create an intermediate buffer to blit to,
+ * before its copied using 'glReadPixels' */
+
+ /* not needed since 'ofs' needs to be bound to the framebuffer already */
+// #define USE_FBO_CTX_SWITCH
+
+ GLuint fbo_blit = 0;
+ GLuint tex_blit = 0;
+ GLenum status;
+
+ /* create texture for new 'fbo_blit' */
+ glGenTextures(1, &tex_blit);
+ if (!tex_blit) {
+ goto finally;
+ }
+
+ glBindTexture(GL_TEXTURE_2D, tex_blit);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, type, 0);
+
+#ifdef USE_FBO_CTX_SWITCH
+ /* read from multi-sample buffer */
+ glBindFramebufferEXT(GL_READ_FRAMEBUFFER, ofs->color->fb->object);
+ glFramebufferTexture2DEXT(
+ GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + ofs->color->fb_attachment,
+ GL_TEXTURE_2D_MULTISAMPLE, ofs->color->bindcode, 0);
+ status = glCheckFramebufferStatus(GL_READ_FRAMEBUFFER);
+ if (status != GL_FRAMEBUFFER_COMPLETE) {
+ goto finally;
+ }
+#endif
+
+ /* write into new single-sample buffer */
+ glGenFramebuffersEXT(1, &fbo_blit);
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_blit);
+ glFramebufferTexture2DEXT(
+ GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ GL_TEXTURE_2D, tex_blit, 0);
+ status = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);
+ if (status != GL_FRAMEBUFFER_COMPLETE) {
+ goto finally;
+ }
+
+ /* perform the copy */
+ glBlitFramebufferEXT(0, 0, w, h, 0, 0, w, h, GL_COLOR_BUFFER_BIT, GL_NEAREST);
+
+ /* read the results */
+ glBindFramebufferEXT(GL_READ_FRAMEBUFFER, fbo_blit);
+ glReadPixels(0, 0, w, h, GL_RGBA, type, pixels);
+
+#ifdef USE_FBO_CTX_SWITCH
+ /* restore the original frame-bufer */
+ glBindFramebufferEXT(GL_FRAMEBUFFER, ofs->color->fb->object);
+#undef USE_FBO_CTX_SWITCH
+#endif
+
+
+finally:
+ /* cleanup */
+ if (tex_blit) {
+ glDeleteTextures(1, &tex_blit);
+ }
+ if (fbo_blit) {
+ glDeleteFramebuffersEXT(1, &fbo_blit);
+ }
+
+ GPU_ASSERT_NO_GL_ERRORS("Read Multi-Sample Pixels");
+ }
+ else {
+ glReadPixels(0, 0, w, h, GL_RGBA, type, pixels);
+ }
}
int GPU_offscreen_width(const GPUOffScreen *ofs)
{
- return ofs->color->w;
+ return ofs->color->w_orig;
}
int GPU_offscreen_height(const GPUOffScreen *ofs)
{
- return ofs->color->h;
+ return ofs->color->h_orig;
+}
+
+int GPU_offscreen_color_texture(const GPUOffScreen *ofs)
+{
+ return ofs->color->bindcode;
}
/* GPUShader */
@@ -1533,7 +1671,7 @@ static const char *gpu_shader_version(bool use_opensubdiv)
{
#ifdef WITH_OPENSUBDIV
if (use_opensubdiv) {
- return "#version 150";
+ return "#version 130\n";
}
#else
UNUSED_VARS(use_opensubdiv);
@@ -1550,16 +1688,21 @@ static const char *gpu_shader_version(bool use_opensubdiv)
}
-static void gpu_shader_standard_extensions(char defines[MAX_EXT_DEFINE_LENGTH])
+static void gpu_shader_standard_extensions(char defines[MAX_EXT_DEFINE_LENGTH], bool use_opensubdiv)
{
#ifdef WITH_OPENSUBDIV
- strcat(defines, "#extension GL_ARB_texture_query_lod: enable\n"
- "#extension GL_ARB_gpu_shader5 : enable\n"
- "#extension GL_ARB_explicit_attrib_location : require\n");
+ if (use_opensubdiv) {
+ strcat(defines, "#extension GL_ARB_texture_query_lod: enable\n"
+ "#extension GL_ARB_gpu_shader5 : enable\n"
+ "#extension GL_ARB_explicit_attrib_location : require\n");
+ }
+ else if (GPU_bicubic_bump_support())
+ strcat(defines, "#extension GL_ARB_texture_query_lod: enable\n");
#else
/* need this extension for high quality bump mapping */
if (GPU_bicubic_bump_support())
strcat(defines, "#extension GL_ARB_texture_query_lod: enable\n");
+ (void) use_opensubdiv;
#endif
if (GPU_geometry_shader_support())
@@ -1674,16 +1817,42 @@ void GPU_program_parameter_4f(GPUProgram *program, unsigned int location, float
glProgramLocalParameter4fARB(program->type, location, x, y, z, w);
}
-
-
-GPUShader *GPU_shader_create(const char *vertexcode, const char *fragcode, const char *geocode, const char *libcode, const char *defines, int input, int output, int number)
+GPUShader *GPU_shader_create(const char *vertexcode,
+ const char *fragcode,
+ const char *geocode,
+ const char *libcode,
+ const char *defines,
+ int input,
+ int output,
+ int number)
+{
+ return GPU_shader_create_ex(vertexcode,
+ fragcode,
+ geocode,
+ libcode,
+ defines,
+ input,
+ output,
+ number,
+ GPU_SHADER_FLAGS_NONE);
+}
+
+GPUShader *GPU_shader_create_ex(const char *vertexcode,
+ const char *fragcode,
+ const char *geocode,
+ const char *libcode,
+ const char *defines,
+ int input,
+ int output,
+ int number,
+ const int flags)
{
-#ifdef WITH_OPENSUBDIF
+#ifdef WITH_OPENSUBDIV
/* TODO(sergey): used to add #version 150 to the geometry shader.
- * Could safely be renamed to "use_geometry_code" since it's evry much
- * liely any of geometry code will want to use GLSL 1.5.
+ * Could safely be renamed to "use_geometry_code" since it's very
+ * likely any of geometry code will want to use GLSL 1.5.
*/
- bool use_opensubdiv = geocode != NULL;
+ bool use_opensubdiv = (flags & GPU_SHADER_FLAGS_SPECIAL_OPENSUBDIV) != 0;
#else
bool use_opensubdiv = false;
#endif
@@ -1694,6 +1863,10 @@ GPUShader *GPU_shader_create(const char *vertexcode, const char *fragcode, const
char standard_defines[MAX_DEFINE_LENGTH] = "";
char standard_extensions[MAX_EXT_DEFINE_LENGTH] = "";
+#ifndef WITH_OPENSUBDIV
+ UNUSED_VARS(flags);
+#endif
+
if (!GLEW_ARB_vertex_shader || !GLEW_ARB_fragment_shader || (geocode && !GPU_geometry_shader_support()))
return NULL;
@@ -1719,7 +1892,7 @@ GPUShader *GPU_shader_create(const char *vertexcode, const char *fragcode, const
}
gpu_shader_standard_defines(use_opensubdiv, standard_defines);
- gpu_shader_standard_extensions(standard_extensions);
+ gpu_shader_standard_extensions(standard_extensions, use_opensubdiv);
if (vertexcode) {
const char *source[5];
@@ -1850,7 +2023,7 @@ GPUShader *GPU_shader_create(const char *vertexcode, const char *fragcode, const
#ifdef WITH_OPENSUBDIV
/* TODO(sergey): Find a better place for this. */
- {
+ if (use_opensubdiv && GLEW_VERSION_4_1) {
glProgramUniform1i(shader->object,
glGetUniformLocation(shader->object, "FVarDataBuffer"),
31); /* GL_TEXTURE31 */
@@ -1932,7 +2105,7 @@ int GPU_shader_get_uniform(GPUShader *shader, const char *name)
void GPU_shader_uniform_vector(GPUShader *UNUSED(shader), int location, int length, int arraysize, const float *value)
{
- if (location == -1)
+ if (location == -1 || value == NULL)
return;
GPU_ASSERT_NO_GL_ERRORS("Pre Uniform Vector");
diff --git a/source/blender/gpu/intern/gpu_init_exit.c b/source/blender/gpu/intern/gpu_init_exit.c
index 3a8a6fca23b..da4dd65d2e1 100644
--- a/source/blender/gpu/intern/gpu_init_exit.c
+++ b/source/blender/gpu/intern/gpu_init_exit.c
@@ -49,7 +49,7 @@ static bool initialized = false;
void GPU_init(void)
{
- /* can't avoid calling this multiple times, see wm_window_add_ghostwindow */
+ /* can't avoid calling this multiple times, see wm_window_ghostwindow_add */
if (initialized)
return;
diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c
index 5b647232934..82902f8d69c 100644
--- a/source/blender/gpu/intern/gpu_material.c
+++ b/source/blender/gpu/intern/gpu_material.c
@@ -141,6 +141,7 @@ struct GPULamp {
float dynimat[4][4];
float spotsi, spotbl, k;
+ float spotvec[2];
float dyndist, dynatt1, dynatt2;
float dist, att1, att2;
float shadow_color[3];
@@ -536,12 +537,15 @@ static GPUNodeLink *lamp_get_visibility(GPUMaterial *mat, GPULamp *lamp, GPUNode
if (lamp->type == LA_SPOT) {
if (lamp->mode & LA_SQUARE) {
- mat->dynproperty |= DYN_LAMP_VEC|DYN_LAMP_IMAT;
- GPU_link(mat, "lamp_visibility_spot_square", GPU_dynamic_uniform(lamp->dynvec, GPU_DYNAMIC_LAMP_DYNVEC, lamp->ob), GPU_dynamic_uniform((float*)lamp->dynimat, GPU_DYNAMIC_LAMP_DYNIMAT, lamp->ob), *lv, &inpr);
+ mat->dynproperty |= DYN_LAMP_VEC | DYN_LAMP_IMAT;
+ GPU_link(mat, "lamp_visibility_spot_square", GPU_dynamic_uniform(lamp->dynvec, GPU_DYNAMIC_LAMP_DYNVEC, lamp->ob), GPU_dynamic_uniform((float*)lamp->dynimat, GPU_DYNAMIC_LAMP_DYNIMAT, lamp->ob),
+ GPU_dynamic_uniform((float *)lamp->spotvec, GPU_DYNAMIC_LAMP_SPOTSCALE, lamp->ob), *lv, &inpr);
}
else {
- mat->dynproperty |= DYN_LAMP_VEC;
- GPU_link(mat, "lamp_visibility_spot_circle", GPU_dynamic_uniform(lamp->dynvec, GPU_DYNAMIC_LAMP_DYNVEC, lamp->ob), *lv, &inpr);
+ mat->dynproperty |= DYN_LAMP_VEC | DYN_LAMP_IMAT;
+ GPU_link(mat, "lamp_visibility_spot_circle", GPU_dynamic_uniform(lamp->dynvec, GPU_DYNAMIC_LAMP_DYNVEC, lamp->ob),
+ GPU_dynamic_uniform((float *)lamp->dynimat, GPU_DYNAMIC_LAMP_DYNIMAT, lamp->ob),
+ GPU_dynamic_uniform((float *)lamp->spotvec, GPU_DYNAMIC_LAMP_SPOTSCALE, lamp->ob), *lv, &inpr);
}
GPU_link(mat, "lamp_visibility_spot", GPU_dynamic_uniform(&lamp->spotsi, GPU_DYNAMIC_LAMP_SPOTSIZE, lamp->ob), GPU_dynamic_uniform(&lamp->spotbl, GPU_DYNAMIC_LAMP_SPOTSIZE, lamp->ob), inpr, visifac, &visifac);
@@ -1854,24 +1858,41 @@ static void gpu_lamp_calc_winmat(GPULamp *lamp)
temp = 0.5f * lamp->size * cosf(angle) / sinf(angle);
pixsize = lamp->d / temp;
wsize = pixsize * 0.5f * lamp->size;
- perspective_m4(lamp->winmat, -wsize, wsize, -wsize, wsize, lamp->d, lamp->clipend);
+ if (lamp->type & LA_SPOT) {
+ /* 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);
+ }
+ else {
+ perspective_m4(lamp->winmat, -wsize, wsize, -wsize, wsize, 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;
- copy_m4_m4(mat, obmat);
- normalize_m4(mat);
+ 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);
+
+ /* 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];
+
+ /* makeshadowbuf */
+ gpu_lamp_calc_winmat(lamp);
}
void GPU_lamp_update_colors(GPULamp *lamp, float r, float g, float b, float energy)
@@ -1895,8 +1916,6 @@ void GPU_lamp_update_spot(GPULamp *lamp, float spotsize, float spotblend)
{
lamp->spotsi = cosf(spotsize * 0.5f);
lamp->spotbl = (1.0f - lamp->spotsi) * spotblend;
-
- gpu_lamp_calc_winmat(lamp);
}
static void gpu_lamp_from_blender(Scene *scene, Object *ob, Object *par, Lamp *la, GPULamp *lamp)
@@ -1941,9 +1960,6 @@ static void gpu_lamp_from_blender(Scene *scene, Object *ob, Object *par, Lamp *l
/* arbitrary correction for the fact we do no soft transition */
lamp->bias *= 0.25f;
-
- /* makeshadowbuf */
- gpu_lamp_calc_winmat(lamp);
}
static void gpu_lamp_shadow_free(GPULamp *lamp)
diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl
index 54864b2b185..5b62739b0eb 100644
--- a/source/blender/gpu/shaders/gpu_shader_material.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_material.glsl
@@ -149,6 +149,7 @@ void geom(vec3 co, vec3 nor, mat4 viewinvmat, vec3 attorco, vec2 attuv, vec4 att
uv_attribute(attuv, uv);
normal = -normalize(nor); /* blender render normal is negated */
vcol_attribute(attvcol, vcol);
+ srgb_to_linearrgb(vcol, vcol);
vcol_alpha = attvcol.a;
frontback = (gl_FrontFacing)? 1.0: 0.0;
}
@@ -1583,11 +1584,13 @@ void lamp_visibility_sphere(float lampdist, float dist, float visifac, out float
outvisifac= visifac*max(t, 0.0)/lampdist;
}
-void lamp_visibility_spot_square(vec3 lampvec, mat4 lampimat, vec3 lv, out float inpr)
+void lamp_visibility_spot_square(vec3 lampvec, mat4 lampimat, vec2 scale, vec3 lv, out float inpr)
{
if(dot(lv, lampvec) > 0.0) {
vec3 lvrot = (lampimat*vec4(lv, 0.0)).xyz;
- float x = max(abs(lvrot.x/lvrot.z), abs(lvrot.y/lvrot.z));
+ /* without clever non-uniform scale, we could do: */
+ // float x = max(abs(lvrot.x / lvrot.z), abs(lvrot.y / lvrot.z));
+ float x = max(abs((lvrot.x / scale.x) / lvrot.z), abs((lvrot.y / scale.y) / lvrot.z));
inpr = 1.0/sqrt(1.0 + x*x);
}
@@ -1595,9 +1598,21 @@ void lamp_visibility_spot_square(vec3 lampvec, mat4 lampimat, vec3 lv, out float
inpr = 0.0;
}
-void lamp_visibility_spot_circle(vec3 lampvec, vec3 lv, out float inpr)
+void lamp_visibility_spot_circle(vec3 lampvec, mat4 lampimat, vec2 scale, vec3 lv, out float inpr)
{
- inpr = dot(lv, lampvec);
+ /* without clever non-uniform scale, we could do: */
+ // inpr = dot(lv, lampvec);
+ if (dot(lv, lampvec) > 0.0) {
+ vec3 lvrot = (lampimat * vec4(lv, 0.0)).xyz;
+ float x = abs(lvrot.x / lvrot.z);
+ float y = abs(lvrot.y / lvrot.z);
+
+ float ellipse = abs((x * x) / (scale.x * scale.x) + (y * y) / (scale.y * scale.y));
+
+ inpr = 1.0 / sqrt(1.0 + ellipse);
+ }
+ else
+ inpr = 0.0;
}
void lamp_visibility_spot(float spotsi, float spotbl, float inpr, float visifac, out float outvisifac)