EXTERN_C_ENTER JNIEXPORT void JNICALL Java_org_lwjgl_opengl_ARBDrawInstanced_glDrawArraysInstancedARB(JNIEnv *__env, jclass clazz, jint mode, jint first, jint count, jint primcount) { glDrawArraysInstancedARBPROC glDrawArraysInstancedARB = (glDrawArraysInstancedARBPROC)tlsGetFunction(1108); UNUSED_PARAM(clazz) glDrawArraysInstancedARB(mode, first, count, primcount); }
void piglit_init(int argc, char **argv) { bool pass = true; GLuint list; piglit_require_extension("GL_ARB_draw_instanced"); list = glGenLists(1); glNewList(list, GL_COMPILE); glDrawArraysInstancedARB(GL_TRIANGLES, 0, 2, 3); if (!piglit_check_gl_error(GL_INVALID_OPERATION)) pass = false; glDrawElementsInstancedARB(GL_TRIANGLES, 2, GL_UNSIGNED_INT, NULL, 3); if (!piglit_check_gl_error(GL_INVALID_OPERATION)) pass = false; glEndList(); /* Make sure the list is empty. */ glCallList(list); if (!piglit_check_gl_error(0)) pass = false; piglit_report_result(pass ? PIGLIT_PASS : PIGLIT_FAIL); }
void piglit_init(int argc, char **argv) { bool pass = true; piglit_require_extension("GL_ARB_draw_instanced"); glDrawArraysInstancedARB(GL_TRIANGLES, -1, 2, 3); if (!piglit_check_gl_error(GL_INVALID_VALUE)) pass = false; glDrawElementsInstancedARB(GL_TRIANGLES, 2, GL_INT, NULL, 3); if (!piglit_check_gl_error(GL_INVALID_ENUM)) pass = false; glDrawElementsInstancedARB(GL_TRIANGLES, 2, GL_SHORT, NULL, 3); if (!piglit_check_gl_error(GL_INVALID_ENUM)) pass = false; glDrawElementsInstancedARB(GL_TRIANGLES, 2, GL_BYTE, NULL, 3); if (!piglit_check_gl_error(GL_INVALID_ENUM)) pass = false; glDrawElementsInstancedARB(GL_TRIANGLES, 2, GL_FLOAT, NULL, 3); if (!piglit_check_gl_error(GL_INVALID_ENUM)) pass = false; piglit_report_result(pass ? PIGLIT_PASS : PIGLIT_FAIL); }
void InstancingApp::Render(void) { glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT); glUseProgram(instancingProg); glBindVertexArray(square_vao); glDrawArraysInstancedARB(GL_TRIANGLE_FAN, 0, 4, 4); }
static GLboolean test_instancing(GLuint divisor) { static const GLfloat verts[4][2] = { {-1, -1}, {1, -1}, {1, 1}, {-1, 1} }; glVertexPointer(2, GL_FLOAT, 0, verts); glEnableClientState(GL_VERTEX_ARRAY); glVertexAttribPointer(PosAttrib, 2, GL_FLOAT, GL_FALSE, 0, Positions); glVertexAttribPointer(ColorAttrib, 4, GL_FLOAT, GL_FALSE, 0, Colors); glEnableVertexAttribArray(PosAttrib); glEnableVertexAttribArray(ColorAttrib); glVertexAttribDivisorARB(PosAttrib, 1); /* advance color once every 'n' instances */ glVertexAttribDivisorARB(ColorAttrib, divisor); glClear(GL_COLOR_BUFFER_BIT); glUseProgram(Program); glDrawArraysInstancedARB(GL_POLYGON, 0, 4, PRIMS); glUseProgram(0); { GLint i; GLint pos[4]; for (i = 0; i < PRIMS; i++) { GLuint elem = i / divisor; /* use glRasterPos to determine where to read a sample pixel */ glRasterPos2fv(Positions[i]); glGetIntegerv(GL_CURRENT_RASTER_POSITION, pos); if (!piglit_probe_pixel_rgba(pos[0], pos[1], Colors[elem])) { fprintf(stderr, "%s: instance %d failed to draw correctly\n", TestName, i); fprintf(stderr, "%s: color instance divisor = %u\n", TestName, divisor); glutSwapBuffers(); return GL_FALSE; } } } glDisableClientState(GL_VERTEX_ARRAY); glDisableVertexAttribArray(PosAttrib); glDisableVertexAttribArray(ColorAttrib); glutSwapBuffers(); return GL_TRUE; }
inline void VL_glDrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei primcount) { if (glDrawArraysInstanced) glDrawArraysInstanced(mode, first, count, primcount); else if (glDrawArraysInstancedARB) glDrawArraysInstancedARB(mode, first, count, primcount); else if (glDrawArraysInstancedEXT) glDrawArraysInstancedEXT(mode, first, count, primcount); else VL_UNSUPPORTED_FUNC(); }
// Called to draw scene void RenderScene(void) { static CStopWatch rotTimer; // Clear the window and the depth buffer glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); modelViewMatrix.PushMatrix(viewFrame); modelViewMatrix.Translate(0.0f, 0.0f, 800.0f); modelViewMatrix.Rotate(-12.0, 1.0f, 0.0f, 0.0f); modelViewMatrix.Rotate(rotTimer.GetElapsedSeconds() * 15.0f, 0.0f, 1.0f, 0.0f); glUseProgram(grassShader); glUniformMatrix4fv(locMVP, 1, GL_FALSE, transformPipeline.GetModelViewProjectionMatrix()); glBindVertexArray(vao); glDrawArraysInstancedARB(GL_TRIANGLE_STRIP, 0, 6, 1024 * 1024); modelViewMatrix.PopMatrix(); glutSwapBuffers(); glutPostRedisplay(); }
bool GPU_fx_do_composite_pass( GPUFX *fx, float projmat[4][4], bool is_persp, struct Scene *scene, struct GPUOffScreen *ofs) { GPUTexture *src, *target; int numslots = 0; float invproj[4][4]; int i; float dfdyfac[2]; /* number of passes left. when there are no more passes, the result is passed to the frambuffer */ int passes_left = fx->num_passes; /* 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} }; if (fx->effects == 0) return false; GPU_get_dfdy_factors(dfdyfac); /* first, unbind the render-to-texture framebuffer */ GPU_framebuffer_texture_detach(fx->color_buffer); GPU_framebuffer_texture_detach(fx->depth_buffer); if (fx->restore_stencil) glPopAttrib(); src = fx->color_buffer; target = fx->color_buffer_sec; /* set up quad buffer */ glBindBuffer(GL_ARRAY_BUFFER, fx->vbuffer); glVertexPointer(2, GL_FLOAT, 0, NULL); glTexCoordPointer(2, GL_FLOAT, 0, ((GLubyte *)NULL + 8 * sizeof(float))); glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); /* full screen FX pass */ /* invert the view matrix */ invert_m4_m4(invproj, projmat); /* 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; } /* we need to store the differences */ viewvecs[1][0] -= viewvecs[0][0]; viewvecs[1][1] = viewvecs[2][1] - 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]); viewvecs[1][2] = vec_far[2] - viewvecs[0][2]; } /* set invalid color in case shader fails */ glColor3f(1.0, 0.0, 1.0); glDisable(GL_DEPTH_TEST); /* ssao pass */ if (fx->effects & GPU_FX_FLAG_SSAO) { GPUShader *ssao_shader; ssao_shader = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_SSAO, is_persp); if (ssao_shader) { const GPUSSAOSettings *fx_ssao = fx->settings.ssao; int color_uniform, depth_uniform; int ssao_uniform, ssao_color_uniform, viewvecs_uniform, ssao_sample_params_uniform; int ssao_jitter_uniform, ssao_concentric_tex; float ssao_params[4] = {fx_ssao->distance_max, fx_ssao->factor, fx_ssao->attenuation, 0.0f}; float sample_params[3]; sample_params[0] = fx->ssao_sample_count_cache; /* multiplier so we tile the random texture on screen */ sample_params[1] = fx->gbuffer_dim[0] / 64.0; sample_params[2] = fx->gbuffer_dim[1] / 64.0; ssao_params[3] = (passes_left == 1 && !ofs) ? dfdyfac[0] : dfdyfac[1]; ssao_uniform = GPU_shader_get_uniform(ssao_shader, "ssao_params"); ssao_color_uniform = GPU_shader_get_uniform(ssao_shader, "ssao_color"); color_uniform = GPU_shader_get_uniform(ssao_shader, "colorbuffer"); depth_uniform = GPU_shader_get_uniform(ssao_shader, "depthbuffer"); viewvecs_uniform = GPU_shader_get_uniform(ssao_shader, "viewvecs"); ssao_sample_params_uniform = GPU_shader_get_uniform(ssao_shader, "ssao_sample_params"); ssao_concentric_tex = GPU_shader_get_uniform(ssao_shader, "ssao_concentric_tex"); ssao_jitter_uniform = GPU_shader_get_uniform(ssao_shader, "jitter_tex"); GPU_shader_bind(ssao_shader); GPU_shader_uniform_vector(ssao_shader, ssao_uniform, 4, 1, ssao_params); GPU_shader_uniform_vector(ssao_shader, ssao_color_uniform, 4, 1, fx_ssao->color); GPU_shader_uniform_vector(ssao_shader, viewvecs_uniform, 4, 3, viewvecs[0]); GPU_shader_uniform_vector(ssao_shader, ssao_sample_params_uniform, 3, 1, sample_params); GPU_texture_bind(src, numslots++); GPU_shader_uniform_texture(ssao_shader, color_uniform, src); GPU_texture_bind(fx->depth_buffer, numslots++); GPU_texture_filter_mode(fx->depth_buffer, false, true); GPU_shader_uniform_texture(ssao_shader, depth_uniform, fx->depth_buffer); GPU_texture_bind(fx->jitter_buffer, numslots++); GPU_shader_uniform_texture(ssao_shader, ssao_jitter_uniform, fx->jitter_buffer); GPU_texture_bind(fx->ssao_spiral_samples_tex, numslots++); GPU_shader_uniform_texture(ssao_shader, ssao_concentric_tex, fx->ssao_spiral_samples_tex); /* draw */ gpu_fx_bind_render_target(&passes_left, fx, ofs, target); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); /* disable bindings */ GPU_texture_unbind(src); GPU_texture_filter_mode(fx->depth_buffer, true, false); GPU_texture_unbind(fx->depth_buffer); GPU_texture_unbind(fx->jitter_buffer); GPU_texture_unbind(fx->ssao_spiral_samples_tex); /* may not be attached, in that case this just returns */ if (target) { GPU_framebuffer_texture_detach(target); if (ofs) { GPU_offscreen_bind(ofs, false); } else { GPU_framebuffer_restore(); } } /* swap here, after src/target have been unbound */ SWAP(GPUTexture *, target, src); numslots = 0; } } /* second pass, dof */ if (fx->effects & GPU_FX_FLAG_DOF) { const GPUDOFSettings *fx_dof = fx->settings.dof; float dof_params[4]; float scale = scene->unit.system ? scene->unit.scale_length : 1.0f; /* this is factor that converts to the scene scale. focal length and sensor are expressed in mm * unit.scale_length is how many meters per blender unit we have. We want to convert to blender units though * because the shader reads coordinates in world space, which is in blender units. */ float scale_camera = 0.001f / scale; /* we want radius here for the aperture number */ float aperture = 0.5f * scale_camera * fx_dof->focal_length / fx_dof->fstop; dof_params[0] = aperture * fabsf(scale_camera * fx_dof->focal_length / ((fx_dof->focus_distance / scale) - scale_camera * fx_dof->focal_length)); dof_params[1] = fx_dof->focus_distance / scale; dof_params[2] = fx->gbuffer_dim[0] / (scale_camera * fx_dof->sensor); dof_params[3] = fx_dof->num_blades; if (fx->dof_high_quality) { GPUShader *dof_shader_pass1, *dof_shader_pass2, *dof_shader_pass3; /* custom shaders close to the effect described in CryEngine 3 Graphics Gems */ dof_shader_pass1 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_ONE, is_persp); dof_shader_pass2 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_TWO, is_persp); dof_shader_pass3 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_THREE, is_persp); /* error occured, restore framebuffers and return */ if (!(dof_shader_pass1 && dof_shader_pass2 && dof_shader_pass3)) { GPU_framebuffer_texture_unbind(fx->gbuffer, NULL); GPU_framebuffer_restore(); glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); GPU_shader_unbind(); glBindBuffer(GL_ARRAY_BUFFER, 0); return false; } /* pass first, downsample the color buffer to near/far targets and calculate coc texture */ { int depth_uniform, dof_uniform; int viewvecs_uniform; int invrendertargetdim_uniform, color_uniform; float invrendertargetdim[2] = {1.0f / fx->dof_downsampled_w, 1.0f / fx->dof_downsampled_h}; invrendertargetdim_uniform = GPU_shader_get_uniform(dof_shader_pass1, "invrendertargetdim"); color_uniform = GPU_shader_get_uniform(dof_shader_pass1, "colorbuffer"); dof_uniform = GPU_shader_get_uniform(dof_shader_pass1, "dof_params"); invrendertargetdim_uniform = GPU_shader_get_uniform(dof_shader_pass1, "invrendertargetdim"); depth_uniform = GPU_shader_get_uniform(dof_shader_pass1, "depthbuffer"); viewvecs_uniform = GPU_shader_get_uniform(dof_shader_pass1, "viewvecs"); GPU_shader_bind(dof_shader_pass1); GPU_shader_uniform_vector(dof_shader_pass1, dof_uniform, 4, 1, dof_params); GPU_shader_uniform_vector(dof_shader_pass1, invrendertargetdim_uniform, 2, 1, invrendertargetdim); GPU_shader_uniform_vector(dof_shader_pass1, viewvecs_uniform, 4, 3, viewvecs[0]); GPU_shader_uniform_vector(dof_shader_pass1, invrendertargetdim_uniform, 2, 1, invrendertargetdim); GPU_texture_bind(fx->depth_buffer, numslots++); GPU_texture_filter_mode(fx->depth_buffer, false, false); GPU_shader_uniform_texture(dof_shader_pass1, depth_uniform, fx->depth_buffer); GPU_texture_bind(src, numslots++); /* disable filtering for the texture so custom downsample can do the right thing */ GPU_texture_filter_mode(src, false, false); GPU_shader_uniform_texture(dof_shader_pass2, color_uniform, src); /* target is the downsampled coc buffer */ GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_half_downsampled_near, 0, NULL); GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_half_downsampled_far, 1, NULL); GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_nearfar_coc, 2, NULL); /* binding takes care of setting the viewport to the downsampled size */ GPU_framebuffer_slots_bind(fx->gbuffer, 0); GPU_framebuffer_check_valid(fx->gbuffer, NULL); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); /* disable bindings */ GPU_texture_filter_mode(src, false, true); GPU_texture_unbind(src); GPU_texture_filter_mode(fx->depth_buffer, true, false); GPU_texture_unbind(fx->depth_buffer); GPU_framebuffer_texture_detach(fx->dof_half_downsampled_near); GPU_framebuffer_texture_detach(fx->dof_half_downsampled_far); GPU_framebuffer_texture_detach(fx->dof_nearfar_coc); GPU_framebuffer_texture_unbind(fx->gbuffer, fx->dof_half_downsampled_near); numslots = 0; } /* second pass, shoot quads for every pixel in the downsampled buffers, scaling according * to circle of confusion */ { int rendertargetdim_uniform, coc_uniform, color_uniform, select_uniform, dof_uniform; int rendertargetdim[2] = {fx->dof_downsampled_w, fx->dof_downsampled_h}; float selection[2] = {0.0f, 1.0f}; rendertargetdim_uniform = GPU_shader_get_uniform(dof_shader_pass2, "rendertargetdim"); color_uniform = GPU_shader_get_uniform(dof_shader_pass2, "colorbuffer"); coc_uniform = GPU_shader_get_uniform(dof_shader_pass2, "cocbuffer"); select_uniform = GPU_shader_get_uniform(dof_shader_pass2, "layerselection"); dof_uniform = GPU_shader_get_uniform(dof_shader_pass2, "dof_params"); GPU_shader_bind(dof_shader_pass2); GPU_shader_uniform_vector(dof_shader_pass2, dof_uniform, 4, 1, dof_params); GPU_shader_uniform_vector_int(dof_shader_pass2, rendertargetdim_uniform, 2, 1, rendertargetdim); GPU_shader_uniform_vector(dof_shader_pass2, select_uniform, 2, 1, selection); GPU_texture_bind(fx->dof_nearfar_coc, numslots++); GPU_shader_uniform_texture(dof_shader_pass2, coc_uniform, fx->dof_nearfar_coc); GPU_texture_bind(fx->dof_half_downsampled_far, numslots++); GPU_texture_bind(fx->dof_half_downsampled_near, numslots++); GPU_shader_uniform_texture(dof_shader_pass2, color_uniform, fx->dof_half_downsampled_far); GPU_texture_filter_mode(fx->dof_half_downsampled_far, false, false); /* target is the downsampled coc buffer */ GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_far_blur, 0, NULL); GPU_texture_bind_as_framebuffer(fx->dof_far_blur); glDisable(GL_DEPTH_TEST); glEnable(GL_BLEND); glBlendFunc(GL_ONE, GL_ONE); glPointSize(1.0f); /* have to clear the buffer unfortunately */ glClearColor(0.0, 0.0, 0.0, 0.0); glClear(GL_COLOR_BUFFER_BIT); /* the draw call we all waited for, draw a point per pixel, scaled per circle of confusion */ glDrawArraysInstancedARB(GL_POINTS, 0, 1, fx->dof_downsampled_w * fx->dof_downsampled_h); GPU_texture_unbind(fx->dof_half_downsampled_far); GPU_framebuffer_texture_detach(fx->dof_far_blur); GPU_shader_uniform_texture(dof_shader_pass2, color_uniform, fx->dof_half_downsampled_near); GPU_texture_filter_mode(fx->dof_half_downsampled_near, false, false); selection[0] = 1.0f; selection[1] = 0.0f; GPU_shader_uniform_vector(dof_shader_pass2, select_uniform, 2, 1, selection); GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_blur, 0, NULL); /* have to clear the buffer unfortunately */ glClear(GL_COLOR_BUFFER_BIT); /* the draw call we all waited for, draw a point per pixel, scaled per circle of confusion */ glDrawArraysInstancedARB(GL_POINTS, 0, 1, fx->dof_downsampled_w * fx->dof_downsampled_h); /* disable bindings */ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glDisable(GL_BLEND); GPU_framebuffer_texture_detach(fx->dof_near_blur); GPU_texture_unbind(fx->dof_half_downsampled_near); GPU_texture_unbind(fx->dof_nearfar_coc); GPU_framebuffer_texture_unbind(fx->gbuffer, fx->dof_far_blur); } /* third pass, accumulate the near/far blur fields */ { int invrendertargetdim_uniform, near_uniform, color_uniform; int dof_uniform, far_uniform, viewvecs_uniform, depth_uniform; float invrendertargetdim[2] = {1.0f / fx->dof_downsampled_w, 1.0f / fx->dof_downsampled_h}; dof_uniform = GPU_shader_get_uniform(dof_shader_pass3, "dof_params"); invrendertargetdim_uniform = GPU_shader_get_uniform(dof_shader_pass3, "invrendertargetdim"); color_uniform = GPU_shader_get_uniform(dof_shader_pass3, "colorbuffer"); far_uniform = GPU_shader_get_uniform(dof_shader_pass3, "farbuffer"); near_uniform = GPU_shader_get_uniform(dof_shader_pass3, "nearbuffer"); viewvecs_uniform = GPU_shader_get_uniform(dof_shader_pass3, "viewvecs"); depth_uniform = GPU_shader_get_uniform(dof_shader_pass3, "depthbuffer"); GPU_shader_bind(dof_shader_pass3); GPU_shader_uniform_vector(dof_shader_pass3, dof_uniform, 4, 1, dof_params); GPU_shader_uniform_vector(dof_shader_pass3, invrendertargetdim_uniform, 2, 1, invrendertargetdim); GPU_shader_uniform_vector(dof_shader_pass3, viewvecs_uniform, 4, 3, viewvecs[0]); GPU_texture_bind(fx->dof_near_blur, numslots++); GPU_shader_uniform_texture(dof_shader_pass3, near_uniform, fx->dof_near_blur); GPU_texture_filter_mode(fx->dof_near_blur, false, true); GPU_texture_bind(fx->dof_far_blur, numslots++); GPU_shader_uniform_texture(dof_shader_pass3, far_uniform, fx->dof_far_blur); GPU_texture_filter_mode(fx->dof_far_blur, false, true); GPU_texture_bind(fx->depth_buffer, numslots++); GPU_texture_filter_mode(fx->depth_buffer, false, false); GPU_shader_uniform_texture(dof_shader_pass3, depth_uniform, fx->depth_buffer); GPU_texture_bind(src, numslots++); GPU_shader_uniform_texture(dof_shader_pass3, color_uniform, src); /* if this is the last pass, prepare for rendering on the frambuffer */ gpu_fx_bind_render_target(&passes_left, fx, ofs, target); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); /* disable bindings */ GPU_texture_unbind(fx->dof_near_blur); GPU_texture_unbind(fx->dof_far_blur); GPU_texture_unbind(src); GPU_texture_filter_mode(fx->depth_buffer, true, false); GPU_texture_unbind(fx->depth_buffer); /* may not be attached, in that case this just returns */ if (target) { GPU_framebuffer_texture_detach(target); if (ofs) { GPU_offscreen_bind(ofs, false); } else { GPU_framebuffer_restore(); } } numslots = 0; } } else { GPUShader *dof_shader_pass1, *dof_shader_pass2, *dof_shader_pass3, *dof_shader_pass4, *dof_shader_pass5; /* DOF effect has many passes but most of them are performed * on a texture whose dimensions are 4 times less than the original * (16 times lower than original screen resolution). * Technique used is not very exact but should be fast enough and is based * on "Practical Post-Process Depth of Field" * see http://http.developer.nvidia.com/GPUGems3/gpugems3_ch28.html */ dof_shader_pass1 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_ONE, is_persp); dof_shader_pass2 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_TWO, is_persp); dof_shader_pass3 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_THREE, is_persp); dof_shader_pass4 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FOUR, is_persp); dof_shader_pass5 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FIVE, is_persp); /* error occured, restore framebuffers and return */ if (!(dof_shader_pass1 && dof_shader_pass2 && dof_shader_pass3 && dof_shader_pass4 && dof_shader_pass5)) { GPU_framebuffer_texture_unbind(fx->gbuffer, NULL); GPU_framebuffer_restore(); glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); GPU_shader_unbind(); glBindBuffer(GL_ARRAY_BUFFER, 0); return false; } /* pass first, first level of blur in low res buffer */ { int invrendertargetdim_uniform, color_uniform, depth_uniform, dof_uniform; int viewvecs_uniform; float invrendertargetdim[2] = {1.0f / fx->gbuffer_dim[0], 1.0f / fx->gbuffer_dim[1]}; dof_uniform = GPU_shader_get_uniform(dof_shader_pass1, "dof_params"); invrendertargetdim_uniform = GPU_shader_get_uniform(dof_shader_pass1, "invrendertargetdim"); color_uniform = GPU_shader_get_uniform(dof_shader_pass1, "colorbuffer"); depth_uniform = GPU_shader_get_uniform(dof_shader_pass1, "depthbuffer"); viewvecs_uniform = GPU_shader_get_uniform(dof_shader_pass1, "viewvecs"); GPU_shader_bind(dof_shader_pass1); GPU_shader_uniform_vector(dof_shader_pass1, dof_uniform, 4, 1, dof_params); GPU_shader_uniform_vector(dof_shader_pass1, invrendertargetdim_uniform, 2, 1, invrendertargetdim); GPU_shader_uniform_vector(dof_shader_pass1, viewvecs_uniform, 4, 3, viewvecs[0]); GPU_texture_bind(src, numslots++); GPU_shader_uniform_texture(dof_shader_pass1, color_uniform, src); GPU_texture_bind(fx->depth_buffer, numslots++); GPU_texture_filter_mode(fx->depth_buffer, false, true); GPU_shader_uniform_texture(dof_shader_pass1, depth_uniform, fx->depth_buffer); /* target is the downsampled coc buffer */ GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_buffer, 0, NULL); /* binding takes care of setting the viewport to the downsampled size */ GPU_texture_bind_as_framebuffer(fx->dof_near_coc_buffer); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); /* disable bindings */ GPU_texture_unbind(src); GPU_texture_filter_mode(fx->depth_buffer, true, false); GPU_texture_unbind(fx->depth_buffer); GPU_framebuffer_texture_detach(fx->dof_near_coc_buffer); numslots = 0; } /* second pass, gaussian blur the downsampled image */ { int invrendertargetdim_uniform, color_uniform, depth_uniform, dof_uniform; int viewvecs_uniform; float invrendertargetdim[2] = {1.0f / GPU_texture_width(fx->dof_near_coc_blurred_buffer), 1.0f / GPU_texture_height(fx->dof_near_coc_blurred_buffer)}; float tmp = invrendertargetdim[0]; invrendertargetdim[0] = 0.0f; dof_params[2] = GPU_texture_width(fx->dof_near_coc_blurred_buffer) / (scale_camera * fx_dof->sensor); dof_uniform = GPU_shader_get_uniform(dof_shader_pass2, "dof_params"); invrendertargetdim_uniform = GPU_shader_get_uniform(dof_shader_pass2, "invrendertargetdim"); color_uniform = GPU_shader_get_uniform(dof_shader_pass2, "colorbuffer"); depth_uniform = GPU_shader_get_uniform(dof_shader_pass2, "depthbuffer"); viewvecs_uniform = GPU_shader_get_uniform(dof_shader_pass2, "viewvecs"); /* Blurring vertically */ GPU_shader_bind(dof_shader_pass2); GPU_shader_uniform_vector(dof_shader_pass2, dof_uniform, 4, 1, dof_params); GPU_shader_uniform_vector(dof_shader_pass2, invrendertargetdim_uniform, 2, 1, invrendertargetdim); GPU_shader_uniform_vector(dof_shader_pass2, viewvecs_uniform, 4, 3, viewvecs[0]); GPU_texture_bind(fx->depth_buffer, numslots++); GPU_texture_filter_mode(fx->depth_buffer, false, true); GPU_shader_uniform_texture(dof_shader_pass2, depth_uniform, fx->depth_buffer); GPU_texture_bind(fx->dof_near_coc_buffer, numslots++); GPU_shader_uniform_texture(dof_shader_pass2, color_uniform, fx->dof_near_coc_buffer); /* use final buffer as a temp here */ GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_final_buffer, 0, NULL); /* Drawing quad */ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); /* *unbind/detach */ GPU_texture_unbind(fx->dof_near_coc_buffer); GPU_framebuffer_texture_detach(fx->dof_near_coc_final_buffer); /* Blurring horizontally */ invrendertargetdim[0] = tmp; invrendertargetdim[1] = 0.0f; GPU_shader_uniform_vector(dof_shader_pass2, invrendertargetdim_uniform, 2, 1, invrendertargetdim); GPU_texture_bind(fx->dof_near_coc_final_buffer, numslots++); GPU_shader_uniform_texture(dof_shader_pass2, color_uniform, fx->dof_near_coc_final_buffer); GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_blurred_buffer, 0, NULL); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); /* *unbind/detach */ GPU_texture_filter_mode(fx->depth_buffer, true, false); GPU_texture_unbind(fx->depth_buffer); GPU_texture_unbind(fx->dof_near_coc_final_buffer); GPU_framebuffer_texture_detach(fx->dof_near_coc_blurred_buffer); dof_params[2] = fx->gbuffer_dim[0] / (scale_camera * fx_dof->sensor); numslots = 0; } /* third pass, calculate near coc */ { int near_coc_downsampled, near_coc_blurred; near_coc_downsampled = GPU_shader_get_uniform(dof_shader_pass3, "colorbuffer"); near_coc_blurred = GPU_shader_get_uniform(dof_shader_pass3, "blurredcolorbuffer"); GPU_shader_bind(dof_shader_pass3); GPU_texture_bind(fx->dof_near_coc_buffer, numslots++); GPU_shader_uniform_texture(dof_shader_pass3, near_coc_downsampled, fx->dof_near_coc_buffer); GPU_texture_bind(fx->dof_near_coc_blurred_buffer, numslots++); GPU_shader_uniform_texture(dof_shader_pass3, near_coc_blurred, fx->dof_near_coc_blurred_buffer); GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_final_buffer, 0, NULL); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); /* disable bindings */ GPU_texture_unbind(fx->dof_near_coc_buffer); GPU_texture_unbind(fx->dof_near_coc_blurred_buffer); /* unbinding here restores the size to the original */ GPU_framebuffer_texture_detach(fx->dof_near_coc_final_buffer); numslots = 0; } /* fourth pass blur final coc once to eliminate discontinuities */ { int near_coc_downsampled; int invrendertargetdim_uniform; float invrendertargetdim[2] = {1.0f / GPU_texture_width(fx->dof_near_coc_blurred_buffer), 1.0f / GPU_texture_height(fx->dof_near_coc_blurred_buffer)}; near_coc_downsampled = GPU_shader_get_uniform(dof_shader_pass4, "colorbuffer"); invrendertargetdim_uniform = GPU_shader_get_uniform(dof_shader_pass4, "invrendertargetdim"); GPU_shader_bind(dof_shader_pass4); GPU_texture_bind(fx->dof_near_coc_final_buffer, numslots++); GPU_shader_uniform_texture(dof_shader_pass4, near_coc_downsampled, fx->dof_near_coc_final_buffer); GPU_shader_uniform_vector(dof_shader_pass4, invrendertargetdim_uniform, 2, 1, invrendertargetdim); GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_buffer, 0, NULL); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); /* disable bindings */ GPU_texture_unbind(fx->dof_near_coc_final_buffer); /* unbinding here restores the size to the original */ GPU_framebuffer_texture_unbind(fx->gbuffer, fx->dof_near_coc_buffer); GPU_framebuffer_texture_detach(fx->dof_near_coc_buffer); numslots = 0; } /* final pass, merge blurred layers according to final calculated coc */ { int medium_blurred_uniform, high_blurred_uniform, original_uniform, depth_uniform, dof_uniform; int invrendertargetdim_uniform, viewvecs_uniform; float invrendertargetdim[2] = {1.0f / fx->gbuffer_dim[0], 1.0f / fx->gbuffer_dim[1]}; medium_blurred_uniform = GPU_shader_get_uniform(dof_shader_pass5, "mblurredcolorbuffer"); high_blurred_uniform = GPU_shader_get_uniform(dof_shader_pass5, "blurredcolorbuffer"); dof_uniform = GPU_shader_get_uniform(dof_shader_pass5, "dof_params"); invrendertargetdim_uniform = GPU_shader_get_uniform(dof_shader_pass5, "invrendertargetdim"); original_uniform = GPU_shader_get_uniform(dof_shader_pass5, "colorbuffer"); depth_uniform = GPU_shader_get_uniform(dof_shader_pass5, "depthbuffer"); viewvecs_uniform = GPU_shader_get_uniform(dof_shader_pass5, "viewvecs"); GPU_shader_bind(dof_shader_pass5); GPU_shader_uniform_vector(dof_shader_pass5, dof_uniform, 4, 1, dof_params); GPU_shader_uniform_vector(dof_shader_pass5, invrendertargetdim_uniform, 2, 1, invrendertargetdim); GPU_shader_uniform_vector(dof_shader_pass5, viewvecs_uniform, 4, 3, viewvecs[0]); GPU_texture_bind(src, numslots++); GPU_shader_uniform_texture(dof_shader_pass5, original_uniform, src); GPU_texture_bind(fx->dof_near_coc_blurred_buffer, numslots++); GPU_shader_uniform_texture(dof_shader_pass5, high_blurred_uniform, fx->dof_near_coc_blurred_buffer); GPU_texture_bind(fx->dof_near_coc_buffer, numslots++); GPU_shader_uniform_texture(dof_shader_pass5, medium_blurred_uniform, fx->dof_near_coc_buffer); GPU_texture_bind(fx->depth_buffer, numslots++); GPU_texture_filter_mode(fx->depth_buffer, false, true); GPU_shader_uniform_texture(dof_shader_pass5, depth_uniform, fx->depth_buffer); /* if this is the last pass, prepare for rendering on the frambuffer */ gpu_fx_bind_render_target(&passes_left, fx, ofs, target); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); /* disable bindings */ GPU_texture_unbind(fx->dof_near_coc_buffer); GPU_texture_unbind(fx->dof_near_coc_blurred_buffer); GPU_texture_unbind(src); GPU_texture_filter_mode(fx->depth_buffer, true, false); GPU_texture_unbind(fx->depth_buffer); /* may not be attached, in that case this just returns */ if (target) { GPU_framebuffer_texture_detach(target); if (ofs) { GPU_offscreen_bind(ofs, false); } else { GPU_framebuffer_restore(); } } SWAP(GPUTexture *, target, src); numslots = 0; } } } glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glBindBuffer(GL_ARRAY_BUFFER, 0); GPU_shader_unbind(); return true; }
/* * bindShaders - bind buffer data and pass shader variables. * code based on example in http://www.opengl-tutorial.org/intermediate-tutorials/billboards-particles/particles-instancing/ */ void ParticleSystem::bindShaders() { /* Update the buffers that OpenGL uses for rendering */ glBindBuffer(GL_ARRAY_BUFFER, particles_position_buffer); glBufferData(GL_ARRAY_BUFFER, max_particles * 4 * sizeof(GLfloat), NULL, GL_STREAM_DRAW); // Buffer orphaning, a common way to improve streaming perf. See above link for details. glBufferSubData(GL_ARRAY_BUFFER, 0, active_particles * sizeof(GLfloat) * 4, position_size_data); glBindBuffer(GL_ARRAY_BUFFER, particles_color_buffer); glBufferData(GL_ARRAY_BUFFER, max_particles * 4 * sizeof(GLubyte), NULL, GL_STREAM_DRAW); // Buffer orphaning, a common way to improve streaming perf. See above link for details. glBufferSubData(GL_ARRAY_BUFFER, 0, active_particles * sizeof(GLubyte) * 4, color_data); glBindBuffer(GL_ARRAY_BUFFER, particles_age_buffer); glBufferData(GL_ARRAY_BUFFER, max_particles * sizeof(GLfloat), NULL, GL_STREAM_DRAW); // Buffer orphaning, a common way to improve streaming perf. See above link for details. glBufferSubData(GL_ARRAY_BUFFER, 0, active_particles * sizeof(GLfloat), age_data); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // Use our shader glUseProgram(programID); // Bind our texture in Texture Unit 0 glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, texture); glUniform1i(texture_ID, 0); glUniform3f(CameraRight_worldspace_ID, model_view[0][0], model_view[1][0], model_view[2][0]); glUniform3f(CameraUp_worldspace_ID, model_view[0][1], model_view[1][1], model_view[2][1]); glUniformMatrix4fv(ViewProjMatrixID, 1, GL_FALSE, &model_projection[0][0]); /* billboard vertices */ glEnableVertexAttribArray(squareVerticesID); glBindBuffer(GL_ARRAY_BUFFER, billboard_vertex_buffer); glVertexAttribPointer(squareVerticesID, 3, GL_FLOAT, GL_FALSE, 0, (void *)0); /* bind particle attributes */ /* positions of particles' centers */ glEnableVertexAttribArray(xyzsID); glBindBuffer(GL_ARRAY_BUFFER, particles_position_buffer); glVertexAttribPointer(xyzsID, 4, GL_FLOAT, GL_FALSE, 0, (void *)0); /* particles' colors */ glEnableVertexAttribArray(colorID); glBindBuffer(GL_ARRAY_BUFFER, particles_color_buffer); glVertexAttribPointer(colorID, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, (void *)0); /* particles' age */ glEnableVertexAttribArray(ageID); glBindBuffer(GL_ARRAY_BUFFER, particles_age_buffer); glVertexAttribPointer(ageID, 1, GL_FLOAT, GL_TRUE, 0, (void *)0); glVertexAttribDivisorARB(squareVerticesID, 0); // particles vertices : always reuse the same 4 vertices -> 0 glVertexAttribDivisorARB(xyzsID, 1); // positions: one per quad (its center) -> 1 glVertexAttribDivisorARB(colorID, 1); // color: one per quad -> 1 glVertexAttribDivisorARB(ageID, 1); /* age: one per quad */ /* draw each instance */ glDrawArraysInstancedARB(GL_TRIANGLE_STRIP, 0, 4, active_particles); glDisableVertexAttribArray(squareVerticesID); glDisableVertexAttribArray(xyzsID); glDisableVertexAttribArray(colorID); glDisableVertexAttribArray(ageID); }
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_ARBDrawInstanced_nglDrawArraysInstancedARB(JNIEnv *env, jclass clazz, jint mode, jint first, jint count, jint primcount, jlong function_pointer) { glDrawArraysInstancedARBPROC glDrawArraysInstancedARB = (glDrawArraysInstancedARBPROC)((intptr_t)function_pointer); glDrawArraysInstancedARB(mode, first, count, primcount); }
static GLboolean test_instancing(GLuint divisor) { static const GLfloat verts[4][2] = { {-1, -1}, {1, -1}, {1, 1}, {-1, 1} }; GLuint vbo; uintptr_t offset = 0; if (use_vbo) { glGenBuffers(1, &vbo); glBindBuffer(GL_ARRAY_BUFFER, vbo); glBufferData(GL_ARRAY_BUFFER, sizeof(verts) + sizeof(Positions) + sizeof(Colors), NULL, GL_STATIC_DRAW); glBufferSubData(GL_ARRAY_BUFFER, offset, sizeof(verts), verts); glVertexPointer(2, GL_FLOAT, 0, (void*) offset); offset += sizeof(verts); glBufferSubData(GL_ARRAY_BUFFER, offset, sizeof(Positions), Positions); glVertexAttribPointer(PosAttrib, 2, GL_FLOAT, GL_FALSE, 0, (void*) offset); offset += sizeof(Positions); glBufferSubData(GL_ARRAY_BUFFER, offset, sizeof(Colors), Colors); glVertexAttribPointer(ColorAttrib, 4, GL_FLOAT, GL_FALSE, 0, (void*) offset); offset += sizeof(Colors); glBindBuffer(GL_ARRAY_BUFFER, 0); } else { glVertexPointer(2, GL_FLOAT, 0, verts); glVertexAttribPointer(PosAttrib, 2, GL_FLOAT, GL_FALSE, 0, Positions); glVertexAttribPointer(ColorAttrib, 4, GL_FLOAT, GL_FALSE, 0, Colors); } glEnableClientState(GL_VERTEX_ARRAY); glEnableVertexAttribArray(PosAttrib); glEnableVertexAttribArray(ColorAttrib); glVertexAttribDivisorARB(PosAttrib, 1); /* advance color once every 'n' instances */ glVertexAttribDivisorARB(ColorAttrib, divisor); glClear(GL_COLOR_BUFFER_BIT); glUseProgram(Program); glDrawArraysInstancedARB(GL_POLYGON, 0, 4, PRIMS); glUseProgram(0); if (use_vbo) { glDeleteBuffers(1, &vbo); } { GLint i; GLint pos[4]; for (i = 0; i < PRIMS; i++) { GLuint elem = i / divisor; /* use glRasterPos to determine where to read a sample pixel */ glRasterPos2fv(Positions[i]); glGetIntegerv(GL_CURRENT_RASTER_POSITION, pos); if (!piglit_probe_pixel_rgba(pos[0], pos[1], Colors[elem])) { fprintf(stderr, "%s: instance %d failed to draw correctly\n", TestName, i); fprintf(stderr, "%s: color instance divisor = %u\n", TestName, divisor); piglit_present_results(); return GL_FALSE; } } } glDisableClientState(GL_VERTEX_ARRAY); glDisableVertexAttribArray(PosAttrib); glDisableVertexAttribArray(ColorAttrib); piglit_present_results(); return GL_TRUE; }