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);
}
Пример #2
0
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);
}
Пример #4
0
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);
}
Пример #5
0
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();
 }
Пример #7
0
// 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();
}
Пример #8
0
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);
}
Пример #11
0
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;
}