bate's blog

調べたこと実装したことなどを取りとめもなく書きます。

サンプルの三角形を回した

ほぼコピペ
プリミティブをバインドして行列を渡すより、
頂点シェーダーに行列を渡した方がしっくりくる気がするんだが。
付いてるサンプルは全部プリミティブをバインドして行列を渡しているので従う。

rlBindPrimitive(RL_PRIMITIVE, trianglePrimitive);
rlPrimitiveParameterMatrixf(RL_PRIMITIVE, RL_PRIMITIVE_TRANSFORM_MATRIX, glm::value_ptr(r))

glmを使うと楽かな。

#include <stdlib.h>
#include <stdio.h>

#include <OpenRL/rl.h>
#include <CausticGLUT/glut.h>

#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtc/matrix_transform.hpp>

static RLuint indices[3] = { 0, 1, 2 };
static RLfloat positions[3*2] = { 0.0f, 0.0f, 0.9f, 0.0f, 0.0f, 0.9f };

RLprimitive trianglePrimitive;

RLbuffer positionBuffer;
RLbuffer indexBuffer;

RLshader vertexShader;
RLshader rayShader;
RLprogram triangleProgram;

RLshader frameShader;
RLprogram frameProgram;

float angle = 0.0f;

static const char* g_VertexShaderSource =
	"attribute vec4 positionAttribute;\n"
	"void main()\n"
	"{\n"
	"	rl_Position = positionAttribute;\n"
	"}";

static const char* g_RayShaderSource =
	"void main()\n"
	"{\n"
	"	accumulate(vec3(1.0, 0.0, 0.0));\n"
	"}\n";

static const char* g_FrameShaderSource =
	"uniform vec3 cameraPosition;"
	"void setup() { rl_OutputRayCount = 1; }\n"
	"void main()\n"
	"{\n"
	"	createRay();\n"
	"	rl_OutRay.origin = cameraPosition;\n"
	"	rl_OutRay.direction = vec3(rl_FrameCoord.xy/rl_FrameSize.xy-0.5,-1.0);\n"
	"	emitRay();\n"
	"}\n";

RLshader compileShader(const char* source, RLuint shaderType, const char* shaderDescription)
{
	RLint status;
	RLshader shader;
	const char* aStrings[1];

	aStrings[0] = source;
	shader = rlCreateShader(shaderType);
	rlShaderString(shader, RL_SHADER_NAME, shaderDescription);
	rlShaderSource(shader, 1, aStrings, NULL);
	rlCompileShader(shader);
	rlGetShaderiv(shader, RL_COMPILE_STATUS, &status);
	if(status == RL_FALSE) {
		const char* log;
		rlGetShaderString(shader, RL_COMPILE_LOG, &log);
		printf("%s compilation failed:\n%s\n", shaderDescription, log);
		getchar();
		exit(EXIT_FAILURE);
	}
	return shader;
}

RLprogram linkProgram(RLshader shader0, RLshader shader1, const char* programDescription)
{
	RLint status;
	RLprogram program;

	program = rlCreateProgram();
	rlProgramString(program, RL_PROGRAM_NAME, programDescription);
	if(shader0 != RL_NULL_SHADER) {
		rlAttachShader(program, shader0);
	}
	if(shader1 != RL_NULL_SHADER) {
		rlAttachShader(program, shader1);
	}
	rlLinkProgram(program);
	rlGetProgramiv(program, RL_LINK_STATUS, &status);
	if(status == RL_FALSE) {
		const char* log;
		rlGetProgramString(program, RL_LINK_LOG, &log);
		printf("%s linking failed:\n%s\n", programDescription, log);
		getchar();
		exit(EXIT_FAILURE);
	}
	return program;
}

int getAttribLocation(RLprogram program, const char* attribName)
{
	int loc = rlGetAttribLocation(program, attribName);
	if(loc == -1) {
		printf("Attribute %s not found.\n", attribName);
		exit(EXIT_FAILURE);
	}
	return loc;
}

void InitTraiangle()
{
	int positionAttributeLoc;
	vertexShader = compileShader(g_VertexShaderSource, RL_VERTEX_SHADER, "Vertex shader");
	rayShader    = compileShader(g_RayShaderSource, RL_RAY_SHADER, "Ray shader");
	frameShader  = compileShader(g_FrameShaderSource, RL_FRAME_SHADER, "Frame shader");

	triangleProgram = linkProgram(vertexShader, rayShader, "Program");
	frameProgram    = linkProgram(frameShader, RL_NULL_SHADER, "Frame program");

	positionAttributeLoc = getAttribLocation(triangleProgram, "positionAttribute");

	rlGenBuffers(1, &indexBuffer);
	rlBindBuffer(RL_ELEMENT_ARRAY_BUFFER, indexBuffer);
	rlBufferData(RL_ELEMENT_ARRAY_BUFFER, 3*sizeof(RLuint), indices, RL_STATIC_DRAW);

	rlGenBuffers(1, &positionBuffer);
	rlBindBuffer(RL_ARRAY_BUFFER, positionBuffer);
	rlBufferData(RL_ARRAY_BUFFER, 3 * 2 * sizeof(RLfloat), positions, RL_STATIC_DRAW);

	rlGenPrimitives(1, &trianglePrimitive);
	rlBindPrimitive(RL_PRIMITIVE, trianglePrimitive);
	rlPrimitiveParameterString(RL_PRIMITIVE, RL_PRIMITIVE_NAME, "triangle");

	rlUseProgram(triangleProgram);

	rlBindBuffer(RL_ARRAY_BUFFER, positionBuffer);
	rlVertexAttribBuffer(positionAttributeLoc, 2, RL_FLOAT, RL_FALSE, sizeof(RLfloat)*2, 0);

	rlBindBuffer(RL_ELEMENT_ARRAY_BUFFER, indexBuffer);
	rlDrawElements(RL_TRIANGLES, 3, RL_UNSIGNED_INT, 0);

	rlBindPrimitive(RL_PRIMITIVE, RL_NULL_PRIMITIVE);
	rlUseProgram(frameProgram);
	rlClearColor(0.0f, 0.0f, 0.0f, 1.0f);
}

void Reshape(int w, int h)
{
	rlViewport(0, 0, w, h);
}

void Frame()
{
	rlClearColor(0.0f, 0.0f, 0.0f, 1.0f);
	rlClear(RL_COLOR_BUFFER_BIT);
	rlUniform3f(rlGetUniformLocation(frameProgram, "cameraPosition"), 1e-3f, 1e-3f, 1e-3f + 3.0f);
	{
		// 回転
		angle++;
		glm::mat4 imat(1.0f);
		glm::mat4 r(glm::rotate(imat, angle, glm::vec3(0,0,1)));
		rlBindPrimitive(RL_PRIMITIVE, trianglePrimitive);
		rlPrimitiveParameterMatrixf(RL_PRIMITIVE, RL_PRIMITIVE_TRANSFORM_MATRIX, glm::value_ptr(r));
	}
	rlBindPrimitive(RL_PRIMITIVE, RL_NULL_PRIMITIVE);
	rlRenderFrame();

	glutSwapBuffers();
}

void Shutdown()
{
	rlDeleteProgram(triangleProgram);
	rlDeleteShader(vertexShader);
	rlDeleteShader(rayShader);

	rlDeleteProgram(frameProgram);
	rlDeleteShader(frameShader);

	rlDeleteBuffers(1, &indexBuffer);
	rlDeleteBuffers(1, &positionBuffer);

	rlDeletePrimitives(1, &trianglePrimitive);
}

void Keyboard(unsigned char c, int x, int y)
{
	if(c==27) {
		Shutdown();
		exit(EXIT_SUCCESS);
	}
}

void Idle(void)
{
   glutPostRedisplay();
}

int main(int argc, char**argv)
{
	glutInit(&argc, argv);
	glutInitWindowPosition(100, 100);
	glutInitWindowSize(512, 512);
	glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
	glutCreateWindow("Draw A Triangle");

	InitTraiangle();

	glutDisplayFunc(Frame);
	glutIdleFunc(Idle);
	glutReshapeFunc(Reshape);
	glutKeyboardFunc(Keyboard);
	glutShutdownFunc(Shutdown);

	glutMainLoop();

	return 0;
}