Exemplo n.º 1
0
/**
 * @brief Calculates transformation matrix for the model and its tags
 * @note The transformation matrix is only calculated once
 */
static float* R_CalcTransform (entity_t* e)
{
	transform_t* t;
	float* mp;
	float mt[16], mc[16];

	/* check if this entity is already transformed */
	t = &e->transform;

	if (t->processing)
		Com_Error(ERR_DROP, "Ring in entity transformations!");

	if (t->done)
		return t->matrix;

	/* process this matrix */
	t->processing = true;
	mp = nullptr;

	/* do parent object transformations first */
	if (e->tagent) {
		/* tag transformation */
		const model_t* model = e->tagent->model;
		const mAliasTagOrientation_t* current = nullptr;
		const mAliasTagOrientation_t* old = nullptr;
		const animState_t* as = &e->tagent->as;

		R_GetTags(model, e->tagname, as->frame, as->oldframe, &current, &old);
		if (current != nullptr && old != nullptr) {
			float interpolated[16];

			/* parent transformation */
			mp = R_CalcTransform(e->tagent);

			/* do interpolation */
			R_InterpolateTransform(as->backlerp, model->alias.num_frames, current, old, interpolated);

			/* transform */
			GLMatrixMultiply(mp, interpolated, mt);
			mp = mt;
		}
	}

	GLMatrixAssemble(e->origin, e->angles, mc);

	/* combine transformations */
	if (mp)
		GLMatrixMultiply(mp, mc, t->matrix);
	else
		memcpy(t->matrix, mc, sizeof(float) * 16);

	/* matrix elements 12..14 contain (forward) translation vector, which is also the origin of model after transform */
	e->distanceFromViewOrigin = VectorDist(&t->matrix[12], refdef.viewOrigin);

	/* we're done */
	t->done = true;
	t->processing = false;

	return t->matrix;
}
Exemplo n.º 2
0
void Render(float alpha, float elapsedtime)
{
	static float time = 0;

	float lightpos[4]	= { 6, 3, 10, 1 };
	float eye[3]		= { 0, 0, 3 };
	float look[3]		= { 0, 0, 0 };
	float up[3]			= { 0, 1, 0 };

	float view[16];
	float proj[16];
	float world[16];
	float viewproj[16];
	float tmp1[16];
	float tmp2[16];

	glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

	GLMatrixLookAtRH(view, eye, look, up);
	GLMatrixPerspectiveFovRH(proj, (60.0f * 3.14159f) / 180.f,  (float)screenwidth / (float)screenheight, 0.1f, 100.0f);
	
	GLMatrixMultiply(viewproj, view, proj);

	//calculate world matrix
	GLMatrixIdentity(tmp2);
	
	tmp2[12] = -0.108f;		// offset with bb center
	tmp2[13] = -0.7875f;	// offset with bb center

	GLMatrixRotationAxis(tmp1, fmodf(time * 20.0f, 360.0f) * (3.14152f / 180.0f), 1, 0, 0);
	GLMatrixMultiply(world, tmp2, tmp1);

	GLMatrixRotationAxis(tmp2, fmodf(time * 20.0f, 360.0f) * (3.14152f / 180.0f), 0, 1, 0);
	GLMatrixMultiply(world, world, tmp2);

	// render
	time += elapsedtime;

	glUseProgram(program);
	glUniform4fv(uniform_eyePos, 1, eye);
	glUniform4fv(uniform_lightPos, 1, lightpos);
	glUniformMatrix4fv(uniform_matWorld, 1, false, world);
	glUniformMatrix4fv(uniform_matViewProj, 1, false, viewproj);
	{
		mesh->DrawSubset(0);
	}
	glUseProgram(0);

	// check errors
	GLenum err = glGetError();

	if( err != GL_NO_ERROR )
		std::cout << "Error\n";

	SwapBuffers(hdc);
}
Exemplo n.º 3
0
void RenderScene(OpenGLEffect* effect)
{
	float world[16];
	float worldinv[16];
	float tmp[16];

	GLMatrixIdentity(world);

	for( int i = 0; i < numobjects; ++i )
	{
		const SceneObject& obj = objects[i];

		GLMatrixScaling(tmp, obj.scale[0], obj.scale[1], obj.scale[2]);
		GLMatrixRotationAxis(world, obj.angle, 0, 1, 0);
		GLMatrixMultiply(world, tmp, world);

		GLMatrixTranslation(tmp, obj.position[0], obj.position[1], obj.position[2]);
		GLMatrixMultiply(world, world, tmp);

		GLMatrixInverse(worldinv, world);

		effect->SetMatrix("matWorld", world);
		effect->SetMatrix("matWorldInv", worldinv);

		if( obj.type == 0 )
		{
			float uv[] = { 2, 2, 0, 1 };

			effect->SetVector("uv", uv);
			effect->CommitChanges();

			glBindTexture(GL_TEXTURE_2D, texture1);
			box->DrawSubset(0);
		}
		else if( obj.type == 1 )
		{
			float uv[] = { 1, 1, 0, 1 };

			effect->SetVector("uv", uv);
			effect->CommitChanges();

			glBindTexture(GL_TEXTURE_2D, texture2);
			teapot->DrawSubset(0);
		}
	}

	glBindTexture(GL_TEXTURE_2D, 0);
}
Exemplo n.º 4
0
/**
 * @brief Calculates the muzzle for the current weapon the actor is shooting with
 * @param[in] actor The actor that is shooting. Might not be @c nullptr
 * @param[out] muzzle The muzzle vector to spawn the particle at. Might not be @c nullptr. This is not
 * modified if there is no tag for the muzzle found for the weapon or item the actor has
 * in the hand (also see the given shoot type)
 * @param[in] shootType The shoot type to determine which tag of the actor should be used
 * to resolve the world coordinates. Also used to determine which item (or better which hand)
 * should be used to resolve the actor's item.
 */
static void CL_ActorGetMuzzle (const le_t* actor, vec3_t muzzle, shoot_types_t shootType)
{
	if (actor == nullptr)
		return;

	const Item* weapon;
	const char* tag;
	if (IS_SHOT_RIGHT(shootType)) {
		tag = "tag_rweapon";
		weapon = actor->getRightHandItem();
	} else {
		tag = "tag_lweapon";
		weapon = actor->getLeftHandItem();
	}

	if (!weapon || !weapon->def())
		return;

	const objDef_t* od = weapon->def();
	const model_t* model = cls.modelPool[od->idx];
	if (!model)
		Com_Error(ERR_DROP, "Model for item %s is not precached", od->id);

	/* not every weapon has a muzzle tag assigned */
	if (R_GetTagIndexByName(model, "tag_muzzle") == -1)
		return;

	float modifiedMatrix[16];
	if (!R_GetTagMatrix(actor->model1, tag, actor->as.frame, modifiedMatrix))
		Com_Error(ERR_DROP, "Could not find tag %s for actor model %s", tag, actor->model1->name);

	float mc[16];
	GLMatrixAssemble(actor->origin, actor->angles, mc);

	float matrix[16];
	GLMatrixMultiply(mc, modifiedMatrix, matrix);

	R_GetTagMatrix(model, "tag_muzzle", 0, modifiedMatrix);
	GLMatrixMultiply(matrix, modifiedMatrix, mc);

	muzzle[0] = mc[12];
	muzzle[1] = mc[13];
	muzzle[2] = mc[14];
}
void FPSCamera::GetViewVectors(float forward[3], float right[3], float up[3])
{
	float yaw[16];
	float pitch[16];

	// TODO: rollpitchyaw
	GLMatrixRotationAxis(yaw, anglecurve.curr[0], 0, 1, 0);
	GLMatrixRotationAxis(pitch, anglecurve.curr[1], 1, 0, 0);

	GLMatrixMultiply(view, yaw, pitch);

	GLVec3Set(forward, -view[2], -view[6], -view[10]);
	GLVec3Set(right, view[0], view[4], view[8]);
	GLVec3Set(up, view[1], view[5], view[9]);
}
void FPSCamera::Animate(float alpha)
{
	anglecurve.smooth(smoothedangles, alpha);
	body->GetInterpolatedPosition(position, alpha);

	position[1] += (1.8f - CAMERA_RADIUS);

	// recalculate view matrix
	float yaw[16];
	float pitch[16];

	// TODO: rollpitchyaw
	GLMatrixRotationAxis(yaw, smoothedangles[0], 0, 1, 0);
	GLMatrixRotationAxis(pitch, smoothedangles[1], 1, 0, 0);

	GLMatrixMultiply(view, yaw, pitch);

	view[12] = -(position[0] * view[0] + position[1] * view[4] + position[2] * view[8]);
	view[13] = -(position[0] * view[1] + position[1] * view[5] + position[2] * view[9]);
	view[14] = -(position[0] * view[2] + position[1] * view[6] + position[2] * view[10]);
}
Exemplo n.º 7
0
/*	FUNCTION:		GLCreateModelViewMatrix
	ARGUMENTS:		m			destination matrix
					x,y,z		position
					yaw			compass direction, 0-north, 90-east, 180-south, 270-west
					pitch		azimuth, -90 down, 0 forwad, 90 up
					roll		rotation around forward axis
	RETURN:			n/a
	DESCRIPTION:	Position camera
*/
void GLCreateModelViewMatrix(float *m, float x, float y, float z, float yaw, float pitch, float roll)
{
	//	same as gluLookAt
	Quaternion q, qDir, qAzim;
	qAzim.GenerateLocalRotation(pitch + 90.0f, -1.0f, 0.0f, 0.0f);
	qDir.GenerateLocalRotation(yaw, 0.0f, 0.0f, 1.0f);
	q = qAzim * qDir;
	
	if (roll != 0)
	{
		Quaternion qTilt;
		qTilt.GenerateLocalRotation(roll, 0, 0, 1);
		q = qTilt * q;
	}
	q.CreateRotatedQuaternion(m);

	//	move camera
	float mov[16];
	GLCreateIdentityMatrix(mov);
	mov[12] = -x;
	mov[13] = -y;
	mov[14] = -z;
	GLMatrixMultiply(m, m, mov);
}
Exemplo n.º 8
0
bool InitScene()
{
	SetWindowText(hwnd, TITLE);
	Quadron::qGLExtensions::QueryFeatures(hdc);

	if( !Quadron::qGLExtensions::ARB_shader_storage_buffer_object )
		return false;

#ifdef _DEBUG
	if( Quadron::qGLExtensions::ARB_debug_output )
	{
		glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, 0, GL_TRUE);
		glDebugMessageCallback(ReportGLError, 0);
	}
#endif

	glClearColor(0.0f, 0.125f, 0.3f, 1.0f);
	//glClearColor(1, 1, 1, 1);
	glClearDepth(1.0);

	glEnable(GL_CULL_FACE);
	glCullFace(GL_BACK);

	glDepthFunc(GL_LEQUAL);
	glEnable(GL_DEPTH_TEST);

	screenquad = new OpenGLScreenQuad();

	// load objects
	if( !GLCreateMeshFromQM("../media/meshes/cube.qm", &box) )
	{
		MYERROR("Could not load box");
		return false;
	}

	if( !GLCreateMeshFromQM("../media/meshes/dragon.qm", &dragon) )
	{
		MYERROR("Could not load dragon");
		return false;
	}

	if( !GLCreateMeshFromQM("../media/meshes/happy1.qm", &buddha) )
	{
		MYERROR("Could not load buddha");
		return false;
	}

	// create texture
	glGenTextures(1, &white);
	glBindTexture(GL_TEXTURE_2D, white);
	{
		unsigned int wondercolor = 0xffffffff;
		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, &wondercolor);

		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	}

	// create buffers
	size_t headsize = 16;	// start, count, pad, pad
	size_t nodesize = 16;	// color, depth, next, pad
	size_t numlists = screenwidth * screenheight;

	glGenBuffers(1, &headbuffer);
	glGenBuffers(1, &nodebuffer);
	glGenBuffers(1, &counterbuffer);

	glBindBuffer(GL_SHADER_STORAGE_BUFFER, headbuffer);
	glBufferData(GL_SHADER_STORAGE_BUFFER, numlists * headsize, 0, GL_STATIC_DRAW);

	glBindBuffer(GL_SHADER_STORAGE_BUFFER, nodebuffer);
	glBufferData(GL_SHADER_STORAGE_BUFFER, numlists * 4 * nodesize, 0, GL_STATIC_DRAW);	// 120 MB @ 1080p

	glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);

	glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, counterbuffer);
	glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(GLuint), 0, GL_DYNAMIC_DRAW);
	glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, 0);

	// calculate scene bounding box
	OpenGLAABox tmpbox;
	float world[16];
	float tmp[16];

	GLMatrixIdentity(world);

	for( int i = 0; i < numobjects; ++i )
	{
		const SceneObject& obj = objects[i];

		// scaling * rotation * translation
		GLMatrixScaling(tmp, obj.scale[0], obj.scale[1], obj.scale[2]);
		GLMatrixRotationAxis(world, obj.angle, 0, 1, 0);
		GLMatrixMultiply(world, tmp, world);

		GLMatrixTranslation(tmp, obj.position[0], obj.position[1], obj.position[2]);
		GLMatrixMultiply(world, world, tmp);

		if( obj.type == 0 )
			tmpbox = box->GetBoundingBox();
		else if( obj.type == 1 )
			tmpbox = dragon->GetBoundingBox();
		else if( obj.type == 2 )
			tmpbox = buddha->GetBoundingBox();

		tmpbox.TransformAxisAligned(world);

		scenebox.Add(tmpbox.Min);
		scenebox.Add(tmpbox.Max);
	}

	// head pointer initializer
	if( !GLCreateEffectFromFile("../media/shadersGL/basic2D.vert", 0, "../media/shadersGL/initheadpointers.frag", &init) )
	{
		MYERROR("Could not load initializer shader");
		return false;
	}

	// renderer shader
	if( !GLCreateEffectFromFile("../media/shadersGL/basic2D.vert", 0, "../media/shadersGL/renderfragments.frag", &render) )
	{
		MYERROR("Could not load rendering shader");
		return false;
	}

	// fragment collector shader
	if( !GLCreateEffectFromFile("../media/shadersGL/collectfragments.vert", 0, "../media/shadersGL/collectfragments.frag", &collect) )
	{
		MYERROR("Could not load collector shader");
		return false;
	}

	float angles[2] = { 0.25f, -0.7f };
	cameraangle = angles;

	return true;
}
Exemplo n.º 9
0
void Render(float alpha, float elapsedtime)
{
	float world[16];
	float tmp[16];
	float view[16];
	float proj[16];
	float viewproj[16];
	float eye[3]		= { 0, 0.3f, 8 };
	float look[3]		= { 0, 0.3f, 0 };
	float up[3]			= { 0, 1, 0 };
	float clipplanes[2];
	float orient[2];

	cameraangle.smooth(orient, alpha);

	GLMatrixRotationAxis(view, orient[1], 1, 0, 0);
	GLMatrixRotationAxis(tmp, orient[0], 0, 1, 0);
	GLMatrixMultiply(view, view, tmp);

	GLVec3Transform(eye, eye, view);

	GLFitToBox(clipplanes[0], clipplanes[1], eye, look, scenebox);
	GLMatrixPerspectiveFovRH(proj, (60.0f * 3.14159f) / 180.f,  (float)screenwidth / (float)screenheight, clipplanes[0], clipplanes[1]);

	GLMatrixLookAtRH(view, eye, look, up);
	GLMatrixMultiply(viewproj, view, proj);

	// STEP 1: initialize header pointer buffer
	glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
	glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
	glDisable(GL_DEPTH_TEST);
	glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, headbuffer);

	init->SetInt("screenWidth", screenwidth);
	init->Begin();
	{
		screenquad->Draw();
	}
	init->End();

	// STEP 2: collect transparent fragments into lists
	glBindTexture(GL_TEXTURE_2D, white);
	glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, counterbuffer);

	GLuint* counter = (GLuint*)glMapBuffer(GL_ATOMIC_COUNTER_BUFFER, GL_WRITE_ONLY);
	*counter = 0;

	glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
	glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, 0);

	glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, nodebuffer);
	glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, counterbuffer);

	collect->SetMatrix("matView", view);
	collect->SetMatrix("matProj", proj);
	collect->SetInt("screenWidth", screenwidth);

	collect->Begin();
	{
		GLMatrixIdentity(world);

		for( int i = 0; i < numobjects; ++i )
		{
			const SceneObject& obj = objects[i];

			// scaling * rotation * translation
			GLMatrixScaling(tmp, obj.scale[0], obj.scale[1], obj.scale[2]);
			GLMatrixRotationAxis(world, obj.angle, 0, 1, 0);
			GLMatrixMultiply(world, tmp, world);

			GLMatrixTranslation(tmp, obj.position[0], obj.position[1], obj.position[2]);
			GLMatrixMultiply(world, world, tmp);

			collect->SetMatrix("matWorld", world);
			collect->SetVector("matAmbient", &obj.color.r);
			collect->CommitChanges();

			if( obj.type == 0 )
				box->DrawSubset(0);
			else if( obj.type == 1 )
				dragon->DrawSubset(0);
			else if( obj.type == 2 )
				buddha->DrawSubset(0);
		}
	}
	collect->End();

	glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, 0);

	// STEP 3: render
	glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
	glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);

	glEnable(GL_BLEND);
	glBlendFunc(GL_ONE, GL_SRC_ALPHA);

	render->SetInt("screenWidth", screenwidth);

	render->Begin();
	{
		screenquad->Draw();
	}
	render->End();

	glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, 0);
	glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, 0);

	glDisable(GL_BLEND);
	glEnable(GL_DEPTH_TEST);

#ifdef _DEBUG
	// check errors
	GLenum err = glGetError();

	if( err != GL_NO_ERROR )
		std::cout << "Error\n";
#endif

	SwapBuffers(hdc);
	mousedx = mousedy = 0;
}
Exemplo n.º 10
0
void Render(float alpha, float elapsedtime)
{
	float tmp[16];
	float texmat[16];
	float view[16];
	float viewinv[16];
	float proj[16];
	float viewproj[16];
	float lightview[16];
	float lightproj[16];
	float lightviewproj[16];

	float globalambient[4]	= { 0.01f, 0.01f, 0.01f, 1.0f };
	float moonlight[]		= { -0.25f, 0.65f, -1, 0 };
	float mooncolor[]		= { 0.6f, 0.6f, 1, 1 };

	float eye[3]			= { 0, 0, 8 };
	float look[3]			= { 0, 0, 0 };
	float up[3]				= { 0, 1, 0 };

	float screensize[2]		= { (float)screenwidth, (float)screenheight };
	float lightclip[2];
	float clipplanes[2];
	float orient[2];

	// setup camera
	cameraangle.smooth(orient, alpha);

	GLMatrixRotationAxis(view, orient[1], 1, 0, 0);
	GLMatrixRotationAxis(tmp, orient[0], 0, 1, 0);
	GLMatrixMultiply(view, view, tmp);

	GLVec3Transform(eye, eye, view);

	GLFitToBox(clipplanes[0], clipplanes[1], eye, look, scenebox);
	GLMatrixPerspectiveFovRH(proj, (60.0f * 3.14159f) / 180.f,  (float)screenwidth / (float)screenheight, clipplanes[0], clipplanes[1]);

	GLMatrixLookAtRH(view, eye, look, up);
	GLMatrixMultiply(viewproj, view, proj);

	// setup moonlight
	GLMatrixInverse(viewinv, view);
	GLVec3Transform(moonlight, moonlight, viewinv);
	GLVec3Normalize(moonlight, moonlight);

	// should be that value in view space (background is fix)
	// but let y stay in world space, so we see shadow
	moonlight[1] = 0.65f;

	GLMatrixViewVector(lightview, moonlight);
	GLFitToBox(lightproj, lightclip, lightview, scenebox);
	GLMatrixMultiply(lightviewproj, lightview, lightproj);

	// render shadow map
	glClearColor(0, 0, 0, 1);

	varianceshadow->SetMatrix("matViewProj", lightviewproj);
	varianceshadow->SetVector("clipPlanes", lightclip);

	shadowmap->Set();
	{
		glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

		varianceshadow->Begin();
		{
			RenderScene(varianceshadow);
		}
		varianceshadow->End();
	}
	shadowmap->Unset();

	// blur it
	float texelsize[] = { 1.0f / SHADOWMAP_SIZE, 1.0f / SHADOWMAP_SIZE };

	glDepthMask(GL_FALSE);
	glBindTexture(GL_TEXTURE_2D, shadowmap->GetColorAttachment(0));

	boxblur3x3->SetVector("texelSize", texelsize);

	blurredshadow->Set();
	{
		boxblur3x3->Begin();
		{
			screenquad->Draw();
		}
		boxblur3x3->End();
	}
	blurredshadow->Unset();

	glDepthMask(GL_TRUE);

	// STEP 1: z pass
	ambient->SetMatrix("matViewProj", viewproj);
	ambient->SetVector("matAmbient", globalambient);

	framebuffer->Set();
	{
		glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

		// draw background first
		glDisable(GL_DEPTH_TEST);
		glDepthMask(GL_FALSE);
		glBindTexture(GL_TEXTURE_2D, texture3);

		float scaledx = 1360.0f * (screenheight / 768.0f);
		float scale = screenwidth / scaledx;

		GLMatrixTranslation(tmp, -0.5f, 0, 0);
		GLMatrixScaling(texmat, scale, 1, 1);
		GLMatrixMultiply(texmat, tmp, texmat);

		GLMatrixTranslation(tmp, 0.5f, 0, 0);
		GLMatrixMultiply(texmat, texmat, tmp);

		GLMatrixRotationAxis(tmp, M_PI, 0, 0, 1);
		GLMatrixMultiply(texmat, texmat, tmp);

		basic2D->SetMatrix("matTexture", texmat);
		basic2D->Begin();
		{
			screenquad->Draw();
		}
		basic2D->End();

		glEnable(GL_DEPTH_TEST);
		glDepthMask(GL_TRUE);

		// then fill zbuffer
		ambient->Begin();
		{
			RenderScene(ambient);
		}
		ambient->End();
	}
	framebuffer->Unset();

	// STEP 2: cull lights
	if( lightcull && timeout > DELAY )
	{
		lightcull->SetFloat("alpha", alpha);
		lightcull->SetVector("clipPlanes", clipplanes);
		lightcull->SetVector("screenSize", screensize);
		lightcull->SetMatrix("matProj", proj);
		lightcull->SetMatrix("matView", view);
		lightcull->SetMatrix("matViewProj", viewproj);

		glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, counterbuffer);
		GLuint* counter = (GLuint*)glMapBuffer(GL_ATOMIC_COUNTER_BUFFER, GL_WRITE_ONLY);
	
		*counter = 0;
		glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);

		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, headbuffer);
		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, nodebuffer);
		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, lightbuffer);
		glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, counterbuffer);
		glBindTexture(GL_TEXTURE_2D, framebuffer->GetDepthAttachment());

		lightcull->Begin();
		{
			glDispatchCompute(workgroupsx, workgroupsy, 1);
		}
		lightcull->End();

		glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, 0);
		glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, 0);
		glBindTexture(GL_TEXTURE_2D, 0);
	}

	// STEP 3: add some moonlight with shadow
	glEnable(GL_BLEND);
	glBlendFunc(GL_ONE, GL_ONE);
	glDepthMask(GL_FALSE);

	framebuffer->Set();

	shadowedlight->SetMatrix("matViewProj", viewproj);
	shadowedlight->SetMatrix("lightViewProj", lightviewproj);
	shadowedlight->SetVector("eyePos", eye);
	shadowedlight->SetVector("lightPos", moonlight);
	shadowedlight->SetVector("lightColor", mooncolor);
	shadowedlight->SetVector("clipPlanes", lightclip);

	glActiveTexture(GL_TEXTURE1);
	glBindTexture(GL_TEXTURE_2D, blurredshadow->GetColorAttachment(0));
	glActiveTexture(GL_TEXTURE0);

	shadowedlight->Begin();
	{
		RenderScene(shadowedlight);
	}
	shadowedlight->End();

	// STEP 4: accumulate lighting
	if( lightaccum && timeout > DELAY )
	{
		lightaccum->SetMatrix("matViewProj", viewproj);
		lightaccum->SetVector("eyePos", eye);
		lightaccum->SetFloat("alpha", alpha);
		lightaccum->SetInt("numTilesX", workgroupsx);

		lightaccum->Begin();
		{
			RenderScene(lightaccum);
		}
		lightaccum->End();
		
		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, 0);
		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, 0);
		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, 0);
	}

	framebuffer->Unset();

	glDisable(GL_BLEND);
	glDepthMask(GL_TRUE);

	// STEP 4: gamma correct
	glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
	glBindTexture(GL_TEXTURE_2D, framebuffer->GetColorAttachment(0));

	gammacorrect->Begin();
	{
		screenquad->Draw();
	}
	gammacorrect->End();

#ifdef _DEBUG
	// check errors
	GLenum err = glGetError();

	if( err != GL_NO_ERROR )
		std::cout << "Error\n";
#endif

	SwapBuffers(hdc);
	mousedx = mousedy = 0;
}
Exemplo n.º 11
0
bool InitScene()
{
	SetWindowText(hwnd, TITLE);
	Quadron::qGLExtensions::QueryFeatures(hdc);

	hascompute = (Quadron::qGLExtensions::ARB_compute_shader && Quadron::qGLExtensions::ARB_shader_storage_buffer_object);

#ifdef _DEBUG
	if( Quadron::qGLExtensions::ARB_debug_output )
	{
		glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, 0, GL_TRUE);
		glDebugMessageCallback(ReportGLError, 0);
	}
#endif

	glClearColor(0.0f, 0.125f, 0.3f, 1.0f);
	glClearDepth(1.0);

	glEnable(GL_CULL_FACE);
	glCullFace(GL_BACK);

	glDepthFunc(GL_LEQUAL);
	glEnable(GL_DEPTH_TEST);

	// load objects
	if( !GLCreateMeshFromQM("../media/meshes/teapot.qm", &teapot) )
	{
		MYERROR("Could not load teapot");
		return false;
	}

	if( !GLCreateMeshFromQM("../media/meshes/cube.qm", &box) )
	{
		MYERROR("Could not load box");
		return false;
	}

	// calculate scene bounding box
	OpenGLAABox tmpbox;
	float world[16];
	float tmp[16];

	GLMatrixIdentity(world);

	for( int i = 0; i < numobjects; ++i )
	{
		const SceneObject& obj = objects[i];

		// scaling * rotation * translation
		GLMatrixScaling(tmp, obj.scale[0], obj.scale[1], obj.scale[2]);
		GLMatrixRotationAxis(world, obj.angle, 0, 1, 0);
		GLMatrixMultiply(world, tmp, world);

		GLMatrixTranslation(tmp, obj.position[0], obj.position[1], obj.position[2]);
		GLMatrixMultiply(world, world, tmp);

		if( obj.type == 0 )
			tmpbox = box->GetBoundingBox();
		else if( obj.type == 1 )
			tmpbox = teapot->GetBoundingBox();

		tmpbox.TransformAxisAligned(world);

		scenebox.Add(tmpbox.Min);
		scenebox.Add(tmpbox.Max);
	}

	// create render targets
	framebuffer = new OpenGLFramebuffer(screenwidth, screenheight);
	framebuffer->AttachTexture(GL_COLOR_ATTACHMENT0, GLFMT_A16B16G16R16F);
	framebuffer->AttachTexture(GL_DEPTH_ATTACHMENT, GLFMT_D32F);
	
	if( !framebuffer->Validate() )
		return false;

	shadowmap = new OpenGLFramebuffer(SHADOWMAP_SIZE, SHADOWMAP_SIZE);
	shadowmap->AttachTexture(GL_COLOR_ATTACHMENT0, GLFMT_G32R32F, GL_LINEAR);
	shadowmap->AttachRenderbuffer(GL_DEPTH_ATTACHMENT, GLFMT_D24S8);

	if( !shadowmap->Validate() )
		return false;

	blurredshadow = new OpenGLFramebuffer(SHADOWMAP_SIZE, SHADOWMAP_SIZE);
	blurredshadow->AttachTexture(GL_COLOR_ATTACHMENT0, GLFMT_G32R32F, GL_LINEAR);

	if( !blurredshadow->Validate() )
		return false;

	screenquad = new OpenGLScreenQuad();

	// textures
	if( !GLCreateTextureFromFile("../media/textures/wood2.jpg", true, &texture1) )
	{
		MYERROR("Could not load texture");
		return false;
	}

	if( !GLCreateTextureFromFile("../media/textures/marble2.png", true, &texture2) )
	{
		MYERROR("Could not load texture");
		return false;
	}

	if( !GLCreateTextureFromFile("../media/textures/static_sky.jpg", true, &texture3, GLTEX_FLIPX) )
	{
		MYERROR("Could not load texture");
		return false;
	}

	// create buffers
	workgroupsx = (screenwidth + (screenwidth % 16)) / 16;
	workgroupsy = (screenheight + (screenheight % 16)) / 16;

	size_t numtiles = workgroupsx * workgroupsy;
	size_t headsize = 16;	// start, count, pad, pad
	size_t nodesize = 16;	// light index, next, pad, pad

	if( hascompute )
	{
		glGenBuffers(1, &headbuffer);
		glGenBuffers(1, &nodebuffer);
		glGenBuffers(1, &lightbuffer);
		glGenBuffers(1, &counterbuffer);

		glBindBuffer(GL_SHADER_STORAGE_BUFFER, headbuffer);
		glBufferData(GL_SHADER_STORAGE_BUFFER, numtiles * headsize, 0, GL_STATIC_DRAW);

		glBindBuffer(GL_SHADER_STORAGE_BUFFER, nodebuffer);
		glBufferData(GL_SHADER_STORAGE_BUFFER, numtiles * nodesize * 1024, 0, GL_STATIC_DRAW);	// 4 MB

		glBindBuffer(GL_SHADER_STORAGE_BUFFER, lightbuffer);
		glBufferData(GL_SHADER_STORAGE_BUFFER, NUM_LIGHTS * sizeof(LightParticle), 0, GL_DYNAMIC_DRAW);

		UpdateParticles(0, true);

		glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);

		glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, counterbuffer);
		glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(GLuint), 0, GL_DYNAMIC_DRAW);
		glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, 0);
	}

	// load effects
	if( !GLCreateEffectFromFile("../media/shadersGL/basic2D.vert", 0, "../media/shadersGL/basic2D.frag", &basic2D) )
	{
		MYERROR("Could not load basic 2D shader");
		return false;
	}

	if( !GLCreateEffectFromFile("../media/shadersGL/basic2D.vert", 0, "../media/shadersGL/boxblur3x3.frag", &boxblur3x3) )
	{
		MYERROR("Could not load blur shader");
		return false;
	}

	if( !GLCreateEffectFromFile("../media/shadersGL/basic2D.vert", 0, "../media/shadersGL/gammacorrect.frag", &gammacorrect) )
	{
		MYERROR("Could not load gamma correction shader");
		return false;
	}

	if( !GLCreateEffectFromFile("../media/shadersGL/shadowmap_variance.vert", 0, "../media/shadersGL/shadowmap_variance.frag", &varianceshadow) )
	{
		MYERROR("Could not load shadowmap shader");
		return false;
	}

	if( !GLCreateEffectFromFile("../media/shadersGL/blinnphong_variance.vert", 0, "../media/shadersGL/blinnphong_variance.frag", &shadowedlight) )
	{
		MYERROR("Could not load shadowed light shader");
		return false;
	}

	if( !GLCreateEffectFromFile("../media/shadersGL/ambient.vert", 0, "../media/shadersGL/ambient.frag", &ambient) )
	{
		MYERROR("Could not load ambient shader");
		return false;
	}

	if( hascompute )
	{
		// light accumulation shader
		if( !GLCreateEffectFromFile("../media/shadersGL/lightaccum.vert", 0, "../media/shadersGL/lightaccum.frag", &lightaccum) )
		{
			MYERROR("Could not load light accumulation shader");
			return false;
		}

		// light culling shader
		if( !GLCreateComputeProgramFromFile("../media/shadersGL/lightcull.comp", &lightcull) )
		{
			MYERROR("Could not load light culling shader");
			return false;
		}

		lightcull->SetInt("depthSampler", 0);
		lightcull->SetInt("numLights", NUM_LIGHTS);
		lightaccum->SetInt("sampler0", 0);
	}

	float white[] = { 1, 1, 1, 1 };
	
	shadowedlight->SetVector("matSpecular", white);
	shadowedlight->SetInt("sampler0", 0);
	shadowedlight->SetInt("sampler1", 1);

	boxblur3x3->SetInt("sampler0", 0);
	basic2D->SetInt("sampler0", 0);
	gammacorrect->SetInt("sampler0", 0);

	float angles[2] = { 0.25f, -0.7f };
	cameraangle = angles;

	return true;
}
Exemplo n.º 12
0
void Render(float alpha, float elapsedtime)
{
	float world[16];
	float view[16];
	float proj[16];
	float eye[3];

	basiccamera.Animate(alpha);

	basiccamera.GetViewMatrix(view);
	basiccamera.GetProjectionMatrix(proj);
	basiccamera.GetEyePosition(eye);

	GLVec4Set(uniformDTO.vsuniforms.lightPos, 6, 3, 10, 1);
	GLVec4Set(uniformDTO.vsuniforms.eyePos, eye[0], eye[1], eye[2], 1);

	GLMatrixMultiply(uniformDTO.vsuniforms.matViewProj, view, proj);
	GLMatrixScaling(uniformDTO.vsuniforms.matWorld, OBJECT_SCALE, OBJECT_SCALE, OBJECT_SCALE);

	switch( rendermethod ) {
	case 1:	GLVec4Set(uniformDTO.fsuniforms.color, 1, 0, 0, 1); break;
	case 2:	GLVec4Set(uniformDTO.fsuniforms.color, 1, 0.5f, 0, 1); break;
	case 3:	GLVec4Set(uniformDTO.fsuniforms.color, 1, 1, 0, 1); break;
	case 4:	GLVec4Set(uniformDTO.fsuniforms.color, 0, 0.75f, 0, 1); break;
	case 5:	GLVec4Set(uniformDTO.fsuniforms.color, 0, 1, 0, 1); break;

	default:
		break;
	}

	// render pass
	OpenGLEffect*	effect = ((rendermethod > 1) ? effect2 : effect1);
	GLsync			sync = 0;

	if( rendermethod == 1 ) {
		effect1->SetMatrix("matViewProj", uniformDTO.vsuniforms.matViewProj);
		effect1->SetVector("lightPos", uniformDTO.vsuniforms.lightPos);
		effect1->SetVector("eyePos", uniformDTO.vsuniforms.eyePos);
		effect1->SetVector("color", uniformDTO.fsuniforms.color);
	}

	framebuffer->Set();
	glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

	effect->Begin();
	{
		for( int i = 0; i < GRID_SIZE; ++i )
		{
			for( int j = 0; j < GRID_SIZE; ++j )
			{
				for( int k = 0; k < GRID_SIZE; ++k )
				{
					if( currentcopy >= UNIFORM_COPIES ) {
						if( rendermethod == 4 || rendermethod == 2 ) {
							sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
						} else if( rendermethod == 5 ) {
							glBindBuffer(GL_UNIFORM_BUFFER, uniformbuffer3);
							glUnmapBuffer(GL_UNIFORM_BUFFER);

							persistentdata = (EffectUniformBlock*)glMapBufferRange(GL_UNIFORM_BUFFER, 0, UNIFORM_COPIES * sizeof(EffectUniformBlock),
								GL_MAP_WRITE_BIT|GL_MAP_INVALIDATE_BUFFER_BIT|GL_MAP_PERSISTENT_BIT|GL_MAP_COHERENT_BIT);

							assert(persistentdata != 0);

							glBindBuffer(GL_UNIFORM_BUFFER, 0);
							currentcopy = 0;
						}
					}

					uniformDTO.vsuniforms.matWorld[12] = GRID_SIZE * -0.5f + i;
					uniformDTO.vsuniforms.matWorld[13] = GRID_SIZE * -0.5f + j;
					uniformDTO.vsuniforms.matWorld[14] = GRID_SIZE * -0.5f + k;

					if( rendermethod == 1 ) {
						effect1->SetMatrix("matWorld", uniformDTO.vsuniforms.matWorld);
						effect1->CommitChanges();
					} else {
						if( rendermethod == 2 ) {
							if( sync != 0 ) {
								glWaitSync(sync, 0, GL_TIMEOUT_IGNORED);
								glDeleteSync(sync);

								sync = 0;
							}

							glBindBuffer(GL_UNIFORM_BUFFER, uniformbuffer1);
							glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(EffectUniformBlock), &uniformDTO);

							glBindBufferRange(GL_UNIFORM_BUFFER, 0, uniformbuffer1, 0, sizeof(EffectUniformBlock::VertexUniformData));
							glBindBufferRange(GL_UNIFORM_BUFFER, 1, uniformbuffer1, offsetof(EffectUniformBlock, fsuniforms), sizeof(EffectUniformBlock::FragmentUniformData));
						} else if( rendermethod == 3 ) {
							glBindBuffer(GL_UNIFORM_BUFFER, uniformbuffer1);
							void* data = glMapBufferRange(GL_UNIFORM_BUFFER, 0, sizeof(EffectUniformBlock), GL_MAP_WRITE_BIT|GL_MAP_INVALIDATE_RANGE_BIT);
							{
								memcpy(data, &uniformDTO, sizeof(EffectUniformBlock));
							}
							glUnmapBuffer(GL_UNIFORM_BUFFER);

							glBindBufferRange(GL_UNIFORM_BUFFER, 0, uniformbuffer1, 0, sizeof(EffectUniformBlock::VertexUniformData));
							glBindBufferRange(GL_UNIFORM_BUFFER, 1, uniformbuffer1, offsetof(EffectUniformBlock, fsuniforms), sizeof(EffectUniformBlock::FragmentUniformData));
						} else if( rendermethod == 4 ) {
							GLintptr baseoffset = currentcopy * sizeof(EffectUniformBlock);
							GLbitfield flags = GL_MAP_WRITE_BIT|GL_MAP_INVALIDATE_RANGE_BIT|GL_MAP_UNSYNCHRONIZED_BIT;

							if( sync != 0 ) {
								GLenum result = 0;
								GLbitfield waitflags = GL_SYNC_FLUSH_COMMANDS_BIT;

								do {
									result = glClientWaitSync(sync, waitflags, 500000);
									waitflags = 0;

									if( result == GL_WAIT_FAILED ) {
										std::cout << "glClientWaitSync() failed!\n";
										break;
									}
								} while( result == GL_TIMEOUT_EXPIRED );

								glDeleteSync(sync);
								sync = 0;

								currentcopy = 0;
								baseoffset = 0;
							}

							glBindBuffer(GL_UNIFORM_BUFFER, uniformbuffer2);
							
							void* data = glMapBufferRange(GL_UNIFORM_BUFFER, baseoffset, sizeof(EffectUniformBlock), flags);
							assert(data != 0);
							{
								memcpy(data, &uniformDTO, sizeof(EffectUniformBlock));
							}
							glUnmapBuffer(GL_UNIFORM_BUFFER);

							glBindBufferRange(GL_UNIFORM_BUFFER, 0, uniformbuffer2, baseoffset, sizeof(EffectUniformBlock::VertexUniformData));
							glBindBufferRange(GL_UNIFORM_BUFFER, 1, uniformbuffer2, baseoffset + offsetof(EffectUniformBlock, fsuniforms), sizeof(EffectUniformBlock::FragmentUniformData));

							++currentcopy;
						} else if( rendermethod == 5 ) {
							GLintptr baseoffset = currentcopy * sizeof(EffectUniformBlock);
							memcpy(persistentdata + currentcopy, &uniformDTO, sizeof(EffectUniformBlock));

							glBindBufferRange(GL_UNIFORM_BUFFER, 0, uniformbuffer3, baseoffset, sizeof(EffectUniformBlock::VertexUniformData));
							glBindBufferRange(GL_UNIFORM_BUFFER, 1, uniformbuffer3, baseoffset + offsetof(EffectUniformBlock, fsuniforms), sizeof(EffectUniformBlock::FragmentUniformData));

							++currentcopy;
						}
					}

					mesh->DrawSubset(0);
				}
			}
		}
	}
	effect->End();
	framebuffer->Unset();

	// present
	GLMatrixIdentity(world);

	glDisable(GL_DEPTH_TEST);
	glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

	basic2D->SetMatrix("matTexture", world);
	basic2D->Begin();
	{
		glActiveTexture(GL_TEXTURE0);
		glBindTexture(GL_TEXTURE_2D, framebuffer->GetColorAttachment(0));

		screenquad->Draw();
	}
	basic2D->End();

	// render text
	glViewport(5, screenheight - 517, 512, 512);
	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

	float xzplane[4] = { 0, 1, 0, -0.5f };
	GLMatrixReflect(world, xzplane);

	basic2D->SetMatrix("matTexture", world);
	basic2D->Begin();
	{
		glActiveTexture(GL_TEXTURE0);
		glBindTexture(GL_TEXTURE_2D, text1);

		screenquad->Draw();
	}
	basic2D->End();

	glEnable(GL_DEPTH_TEST);
	glDisable(GL_BLEND);
	glViewport(0, 0, screenwidth, screenheight);

	// check errors
	GLenum err = glGetError();

	if( err != GL_NO_ERROR )
		std::cout << "Error\n";

	SwapBuffers(hdc);
}
Exemplo n.º 13
0
void Render(float alpha, float elapsedtime)
{
	static float time = 0;

	float world[16];
	float view[16];
	float proj[16];
	float viewproj[16];
	float viewinv[16];
	float viewprojinv[16];
	float eye[3];
	float clip[4] = { 0, 0, 0, 0 };

	orbitcamera.Animate(alpha);
	orbitcamera.GetViewMatrix(view);
	orbitcamera.GetProjectionMatrix(proj);
	orbitcamera.GetEyePosition(eye);

	clip[0] = orbitcamera.GetNearPlane();
	clip[1] = orbitcamera.GetFarPlane();

	GLMatrixInverse(viewinv, view);
	GLMatrixMultiply(viewproj, view, proj);
	GLMatrixInverse(viewprojinv, viewproj);

	glViewport(0, 0, screenwidth, screenheight);

	if( userefgtao ) {
		// using the reference spheres with GTAO
		refgbuffereffect->SetMatrix("matView", view);
		refgbuffereffect->SetMatrix("matViewInv", viewinv);
		refgbuffereffect->SetMatrix("matViewProjInv", viewprojinv);
		refgbuffereffect->SetVector("eyePos", eye);
		refgbuffereffect->SetVector("clipPlanes", clip);

		RenderReferenceWithGTAO(proj, clip, eye);
	} else {
		// using the reference spheres with path tracing
		RenderReferenceWithPathTracing(viewprojinv, eye, time);
	}

	if( drawtext ) {
		// render text
		glViewport(5, screenheight - 517, 512, 512);
		glDisable(GL_DEPTH_TEST);
		glEnable(GL_BLEND);
		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

		float xzplane[4] = { 0, 1, 0, -0.5f };
		GLMatrixReflect(world, xzplane);

		presenteffect->SetMatrix("matTexture", world);
		presenteffect->Begin();
		{
			glActiveTexture(GL_TEXTURE0);
			glBindTexture(GL_TEXTURE_2D, text1);

			screenquad->Draw();
		}
		presenteffect->End();

		glEnable(GL_DEPTH_TEST);
		glDisable(GL_BLEND);

		GLMatrixIdentity(world);
		presenteffect->SetMatrix("matTexture", world);
	}

	time += elapsedtime;

#ifdef _DEBUG
	GLenum err = glGetError();

	if( err != GL_NO_ERROR )
		std::cout << "Error\n";
#endif

	SwapBuffers(hdc);
}
Exemplo n.º 14
0
//*************************************************************************************************************
void Render(float alpha, float elapsedtime)
{
	OpenGLColor	grcolor(0xffdddddd);
	OpenGLColor	cvcolor(0xff7470ff);
	OpenGLColor	splinecolor(0xff000000);
	OpenGLColor	outsidecolor(0.75f, 0.75f, 0.8f, 1);
	OpenGLColor	insidecolor(1, 0.66f, 0.066f, 1);

	float		world[16];
	float		view[16];
	float		proj[16];
	float		viewproj[16];

	float		pointsize[2]	= { 10.0f / screenwidth, 10.0f / screenheight };
	float		grthickness[2]	= { 1.5f / screenwidth, 1.5f / screenheight };
	float		cvthickness[2]	= { 2.0f / screenwidth, 2.0f / screenheight };
	float		spthickness[2]	= { 3.0f / screenwidth, 3.0f / screenheight };
	float		spviewport[]	= { 0, 0, (float)screenwidth, (float)screenheight };

	float		eye[3]			= { 5, 4, 15 };
	float		look[3]			= { 5, 4, 5 };
	float		up[3]			= { 0, 1, 0 };
	float		lightdir[4]		= { 0, 1, 0, 0 };
	float		fwd[3];
	float		orient[2];

	// play with ortho matrix instead of viewport (line thickness remains constant)
	ConvertToSplineViewport(spviewport[0], spviewport[1]);
	ConvertToSplineViewport(spviewport[2], spviewport[3]);

	GLMatrixIdentity(world);
	GLMatrixOrthoRH(proj, spviewport[0], spviewport[2], spviewport[1], spviewport[3], -1, 1);

	glViewport(0, 0, screenwidth, screenheight);
	glClearColor(1, 1, 1, 1);
	glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
	glDisable(GL_DEPTH_TEST);

	renderlines->SetMatrix("matViewProj", proj);
	renderlines->SetMatrix("matWorld", world);
	renderlines->SetVector("color", &grcolor.r);
	renderlines->SetVector("lineThickness", grthickness);

	renderlines->Begin();
	{
		supportlines->DrawSubset(0);

		renderlines->SetVector("color", &cvcolor.r);
		renderlines->SetVector("lineThickness", cvthickness);
		renderlines->CommitChanges();

		supportlines->DrawSubset(1);

		if( hascompute )
		{
			renderlines->SetVector("lineThickness", spthickness);
			renderlines->SetVector("color", &splinecolor.r);
			renderlines->CommitChanges();

			curve->DrawSubset(0);
		}
	}
	renderlines->End();

	renderpoints->SetMatrix("matViewProj", proj);
	renderpoints->SetMatrix("matWorld", world);
	renderpoints->SetVector("color", &cvcolor.r);
	renderpoints->SetVector("pointSize", pointsize);

	renderpoints->Begin();
	{
		glBindVertexArray(supportlines->GetVertexLayout());
		glDrawArrays(GL_POINTS, 44, numcontrolvertices);
	}
	renderpoints->End();

	// render surface in a smaller viewport
	if( !fullscreen )
	{
		glEnable(GL_SCISSOR_TEST);
		glScissor(screenwidth - surfvpwidth - 10, screenheight - surfvpheight - 10, surfvpwidth, surfvpheight);
	}

	glClearColor(0.0f, 0.125f, 0.3f, 1.0f);
	glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
	glDisable(GL_SCISSOR_TEST);

	glEnable(GL_DEPTH_TEST);

	if( fullscreen )
		glViewport(0, 0, screenwidth, screenheight);
	else
		glViewport(screenwidth - surfvpwidth - 10, screenheight - surfvpheight - 10, surfvpwidth, surfvpheight);

	cameraangle.smooth(orient, alpha);

	GLVec3Subtract(fwd, look, eye);
	GLMatrixRotationYawPitchRoll(view, orient[0], orient[1], 0);
	GLVec3Transform(fwd, fwd, view);
	GLVec3Subtract(eye, look, fwd);

	GLMatrixPerspectiveRH(proj, M_PI / 3, 4.0f / 3.0f, 0.1f, 50.0f);
	GLMatrixLookAtRH(view, eye, look, up);
	GLMatrixMultiply(viewproj, view, proj);

	if( wireframe )
		glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

	glDisable(GL_CULL_FACE);

	if( hascompute )
	{
		rendersurface->SetMatrix("matViewProj", viewproj);
		rendersurface->SetMatrix("matWorld", world);
		rendersurface->SetMatrix("matWorldInv", world); // its id
		rendersurface->SetVector("lightDir", lightdir);
		rendersurface->SetVector("eyePos", eye);
		rendersurface->SetVector("outsideColor", &outsidecolor.r);
		rendersurface->SetVector("insideColor", &insidecolor.r);
		rendersurface->SetInt("isWireMode", wireframe);

		rendersurface->Begin();
		{
			surface->DrawSubset(0);
		}
		rendersurface->End();
	}

	glEnable(GL_CULL_FACE);

	if( wireframe )
		glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);

	// render text
	if( !fullscreen )
	{
		glViewport(3, 0, 800, 130);

		glDisable(GL_DEPTH_TEST);
		glEnable(GL_BLEND);
		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

		float xzplane[4] = { 0, 1, 0, -0.5f };
		GLMatrixReflect(world, xzplane);

		basic2D->SetMatrix("matTexture", world);
		basic2D->SetInt("sampler0", 0);
		basic2D->Begin();
		{
			glBindTexture(GL_TEXTURE_2D, text1);
			screenquad->Draw();
		}
		basic2D->End();

		glEnable(GL_DEPTH_TEST);
		glDisable(GL_BLEND);
	}

#ifdef _DEBUG
	// check errors
	GLenum err = glGetError();

	if( err != GL_NO_ERROR )
		std::cout << "Error\n";
#endif

	SwapBuffers(hdc);
	mousedx = mousedy = 0;
}