Exemplo n.º 1
0
oglplus::Program SpectraSharedObjects::BuildProgramWithXFB(
	const char* prog_name,
	const char** xfb_varyings,
	std::size_t xfb_var_count,
	bool separate_attribs
)
{
	using namespace oglplus;

	Program prog = Program(ObjectDesc(prog_name));

	std::ifstream prog_file;
	OpenResourceFile(prog_file, "glsl", prog_name, ".txt");

	const std::size_t linesize = 1024;
	char line[1024] = {'\0'};

	int line_no = 0;
	while(prog_file.getline(line, linesize).good())
	{
		std::size_t line_len = prog_file.gcount();
		++line_no;
		auto types = EnumValueRange<ShaderType>();
		ShaderType type = ShaderType::Fragment;
		std::size_t name_len = 0;
		while(!types.Empty())
		{
			type = types.Front();
			StrCRef name = EnumValueName(type);
			name_len = name.size();
			if(std::strncmp(line, name.c_str(), name.size()) == 0)
				break;
			types.Next();
		}
		if(types.Empty())
		{
			wxString message = wxString::Format(
				wxGetTranslation(wxT(
					"Invalid shader type in program '%s' "\
					"on line %d: '%s'"
				)),
				wxString(prog_name, wxConvUTF8).c_str(),
				line_no,
				wxString(line, wxConvUTF8).c_str()
			);
			throw std::runtime_error(
				(const char*)message.mb_str(wxConvUTF8)
			);
		}

		// rtrim the name
		for(std::size_t i = name_len+1; i!=line_len; ++i)
		{
			if(std::isspace(line[i]))
			{
				line[i] = '\0';
				break;
			}
		}

		std::ifstream shader_file;
		OpenResourceFile(shader_file, "glsl", line+name_len+1, ".glsl");

		Shader shader(type);
		shader.Source(GLSLSource::FromStream(shader_file));
		shader.Compile();

		prog.AttachShader(shader);
	}

	if(xfb_varyings && xfb_var_count)
	{
		prog.TransformFeedbackVaryings(
			xfb_var_count,
			xfb_varyings,
			separate_attribs
			?TransformFeedbackMode::SeparateAttribs
			:TransformFeedbackMode::InterleavedAttribs
		);
	}

	prog.Link().Use();
	return std::move(prog);
}
Exemplo n.º 2
0
	SphereExample(void)
	 : sphere_instr(make_sphere.Instructions())
	 , sphere_indices(make_sphere.Indices())
	 , hole_count(50)
	 , hole_diameter(0.30f)
	{
		// This shader will be used in transform fedback mode
		// to transform the vertices used to "cut out the holes"
		// the same way the sphere is transformed
		vs_tfb.Source(
			"#version 330\n"
			"uniform mat4 CameraMatrix, ModelMatrix;"
			"uniform float Diameter;"
			"in vec3 Hole;"
			"out vec3 vertTransfHole;"
			"void main(void)"
			"{"
			"	vertTransfHole = ("
			"		CameraMatrix *"
			"		ModelMatrix *"
			"		vec4(Hole * (1.0 + 0.5 * Diameter), 0.0)"
			"	).xyz;"
			"}"
		);
		// compile, setup transform feedback output variables
		// link and use the program
		vs_tfb.Compile();
		prog_tfb.AttachShader(vs_tfb);

		const GLchar* var_name = "vertTransfHole";
		prog_tfb.TransformFeedbackVaryings(
			1, &var_name,
			TransformFeedbackMode::InterleavedAttribs
		);
		prog_tfb.Link();
		prog_tfb.Use();

		Uniform<GLfloat> diameter(prog_tfb, "Diameter");
		diameter.Set(hole_diameter);

		// bind the VAO for the holes
		holes.Bind();

		// bind the VBO for the hole vertices
		hole_verts.Bind(Buffer::Target::Array);
		// and the VBO for the transformed hole vertices captured by tfb
		transf_hole_verts.Bind(Buffer::Target::TransformFeedback);
		{
			std::vector<GLfloat> data;
			make_hole_data(data, hole_count);
			Buffer::Data(Buffer::Target::TransformFeedback, data);
			Buffer::Data(Buffer::Target::Array, data);
			VertexAttribArray attr(prog_tfb, "Hole");
			attr.Setup<Vec3f>();
			attr.Enable();
		}
		transf_hole_verts.BindBase(
			Buffer::IndexedTarget::TransformFeedback,
			0
		);

		// Set the vertex shader source
		vs.Source(
			"#version 330\n"
			"uniform mat4 ProjectionMatrix, CameraMatrix, ModelMatrix;"
			"in vec4 Position;"
			"in vec3 Normal;"
			"out vec3 vertNormal;"
			"out vec3 vertLight;"
			"const vec3 LightPos = vec3(2.0, 3.0, 3.0);"
			"void main(void)"
			"{"
			"	gl_Position = ModelMatrix * Position;"
			"	vertNormal = mat3(ModelMatrix)*Normal;"
			"	vertLight = LightPos-gl_Position.xyz;"
			"	gl_Position = ProjectionMatrix * CameraMatrix * gl_Position;"
			"}"
		);
		// compile it
		vs.Compile();

		// set the fragment shader source
		fs.Source(
			"#version 330\n"
			"in vec3 vertNormal;"
			"in vec3 vertLight;"
			"out vec4 fragColor;"
			"const int HoleCount = 50;"
			"uniform vec3 TransfHole[50];"
			"uniform float Diameter;"
			"void main(void)"
			"{"
			"	int imax = 0;"
			"	float dmax = -1.0;"
			"	for(int i=0; i!=HoleCount; ++i)"
			"	{"
			"		float d = dot(vertNormal, TransfHole[i]);"
			"		if(dmax < d)"
			"		{"
			"			dmax = d;"
			"			imax = i;"
			"		}"
			"	}"
			"	float l = length(vertLight);"
			"	vec3 FragDiff = TransfHole[imax] - vertNormal;"
			"	vec3 FinalNormal = "
			"		length(FragDiff) > Diameter?"
			"		vertNormal:"
			"		normalize(FragDiff+vertNormal*Diameter);"
			"	float i = (l > 0.0) ? dot("
			"		FinalNormal, "
			"		normalize(vertLight)"
			"	) / l : 0.0;"
			"	i = 0.2+max(i*2.5, 0.0);"
			"	fragColor = vec4(i, i, i, 1.0);"
			"}"
		);
		// compile it
		fs.Compile();

		// attach the shaders to the program
		prog.AttachShader(vs);
		prog.AttachShader(fs);
		// link and use it
		prog.Link();
		prog.Use();

		diameter.Set(hole_diameter);

		// bind the VAO for the sphere
		sphere.Bind();

		// bind the VBO for the sphere vertices
		verts.Bind(Buffer::Target::Array);
		{
			std::vector<GLfloat> data;
			GLuint n_per_vertex = make_sphere.Positions(data);
			// upload the data
			Buffer::Data(Buffer::Target::Array, data);
			// setup the vertex attribs array for the vertices
			VertexAttribArray attr(prog, "Position");
			attr.Setup<GLfloat>(n_per_vertex);
			attr.Enable();
		}

		// bind the VBO for the sphere normals
		normals.Bind(Buffer::Target::Array);
		{
			std::vector<GLfloat> data;
			GLuint n_per_vertex = make_sphere.Normals(data);
			// upload the data
			Buffer::Data(Buffer::Target::Array, data);
			// setup the vertex attribs array for the vertices
			VertexAttribArray attr(prog, "Normal");
			attr.Setup<GLfloat>(n_per_vertex);
			attr.Enable();
		}

		gl.ClearColor(0.8f, 0.8f, 0.7f, 0.0f);
		gl.ClearDepth(1.0f);
		gl.Enable(Capability::DepthTest);
	}
Exemplo n.º 3
0
	PickingExample(void)
	 : cube_instr(make_cube.Instructions())
	 , cube_indices(make_cube.Indices())
	 , vs(ShaderType::Vertex, ObjectDesc("Vertex"))
	 , gs(ShaderType::Geometry, ObjectDesc("Geometry"))
	 , fs(ShaderType::Fragment, ObjectDesc("Fragment"))
	{
		// Set the vertex shader source
		vs.Source(
			"#version 330\n"
			"uniform mat4 ProjectionMatrix, CameraMatrix;"
			"in vec4 Position;"
			"out vec3 vertColor;"
			"flat out int vertInstanceID;"
			"void main(void)"
			"{"
			"	float x = gl_InstanceID % 6 - 2.5;"
			"	float y = gl_InstanceID / 6 - 2.5;"
			"	mat4 ModelMatrix = mat4("
			"		 1.0, 0.0, 0.0, 0.0,"
			"		 0.0, 1.0, 0.0, 0.0,"
			"		 0.0, 0.0, 1.0, 0.0,"
			"		 2*x, 2*y, 0.0, 1.0 "
			"	);"
			"	gl_Position = "
			"		ProjectionMatrix *"
			"		CameraMatrix *"
			"		ModelMatrix *"
			"		Position;"
			"	vertColor = vec3("
			"		abs(normalize((ModelMatrix*Position).xy)),"
			"		0.1"
			"	);"
			"	vertInstanceID = gl_InstanceID;"
			"}"
		);
		vs.Compile();

		// Set the geometry shader source
		gs.Source(
			"#version 330\n"
			"layout(triangles) in;"
			"layout(points, max_vertices = 1) out;"

			"flat in int vertInstanceID[];"
			"uniform vec2 MousePos;"

			"out int geomInstanceID;"
			"out float geomDepth;"

			"vec2 barycentric_coords(vec4 a, vec4 b, vec4 c)"
			"{"
			// we'll need normalized device coordinates
			// of the triangle vertices
			"	vec2 ad = vec2(a.x/a.w, a.y/a.w);"
			"	vec2 bd = vec2(b.x/b.w, b.y/b.w);"
			"	vec2 cd = vec2(c.x/c.w, c.y/c.w);"
			"	vec2 u = cd - ad;"
			"	vec2 v = bd - ad;"
			"	vec2 r = MousePos - ad;"
			"	float d00 = dot(u, u);"
			"	float d01 = dot(u, v);"
			"	float d02 = dot(u, r);"
			"	float d11 = dot(v, v);"
			"	float d12 = dot(v, r);"
			"	float id = 1.0 / (d00 * d11 - d01 * d01);"
			"	float ut = (d11 * d02 - d01 * d12) * id;"
			"	float vt = (d00 * d12 - d01 * d02) * id;"
			"	return vec2(ut, vt);"
			"}"

			"vec3 intersection(vec3 a, vec3 b, vec3 c, vec2 bc)"
			"{"
			"	return (c - a)*bc.x + (b - a)*bc.y;"
			"}"

			"bool inside_triangle(vec2 b)"
			"{"
			"	return ("
			"		(b.x >= 0.0) &&"
			"		(b.y >= 0.0) &&"
			"		(b.x + b.y <= 1.0)"
			"	);"
			"}"

			"void main(void)"
			"{"
			"	vec2 bc = barycentric_coords("
			"		gl_in[0].gl_Position,"
			"		gl_in[1].gl_Position,"
			"		gl_in[2].gl_Position "
			"	);"
			"	if(inside_triangle(bc))"
			"	{"
			"		gl_Position = vec4(intersection("
			"			gl_in[0].gl_Position.xyz,"
			"			gl_in[1].gl_Position.xyz,"
			"			gl_in[2].gl_Position.xyz,"
			"			bc"
			"		), 1.0);"
			"		geomDepth = gl_Position.z;"
			"		geomInstanceID = vertInstanceID[0];"
			"		EmitVertex();"
			"		EndPrimitive();"
			"	}"
			"}"
		);
		gs.Compile();

		// set the fragment shader source
		fs.Source(
			"#version 330\n"
			"flat in int vertInstanceID;"
			"in vec3 vertColor;"
			"uniform int Picked;"
			"out vec4 fragColor;"
			"void main(void)"
			"{"
			"	if(vertInstanceID == Picked)"
			"		fragColor = vec4(1.0, 1.0, 1.0, 1.0);"
			"	else fragColor = vec4(vertColor, 1.0);"
			"}"
		);
		fs.Compile();

		// attach the shaders to the picking program
		pick_prog.AttachShader(vs);
		pick_prog.AttachShader(gs);

		const GLchar* var_names[2] = {"geomDepth", "geomInstanceID"};
		pick_prog.TransformFeedbackVaryings(
			2, var_names,
			TransformFeedbackMode::InterleavedAttribs
		);
		pick_prog.Link();

		// attach the shaders to the drawing program
		draw_prog.AttachShader(vs);
		draw_prog.AttachShader(fs);
		draw_prog.Link();

		// bind the VAO for the cube
		cube.Bind();

		// buffer for the picked instance depths and IDs
		picked_instances.Bind(Buffer::Target::TransformFeedback);
		picked_instances.BindBase(
			Buffer::IndexedTarget::TransformFeedback,
			0
		);
		{
			std::vector<DepthAndID> data(36, DepthAndID(0.0, 0));
			Buffer::Data(Buffer::Target::TransformFeedback, data);
		}

		// bind the VBO for the cube vertices
		verts.Bind(Buffer::Target::Array);
		{
			// make and upload the vertex data
			std::vector<GLfloat> data;
			GLuint n_per_vertex = make_cube.Positions(data);
			Buffer::Data(Buffer::Target::Array, data);

			// setup the vertex attribs array for the vertices
			VertexAttribArray draw_attr(draw_prog, "Position");
			draw_attr.Setup<GLfloat>(n_per_vertex);
			draw_attr.Enable();
		}

		gl.ClearColor(0.9f, 0.9f, 0.9f, 0.0f);
		gl.ClearDepth(1.0f);
		gl.Enable(Capability::DepthTest);

		gl.FrontFace(make_cube.FaceWinding());
		gl.CullFace(Face::Back);
		gl.Enable(Capability::CullFace);
	}