bate's blog

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

GLFW3.0.1とGLEW1.10.0での簡易サンプル

VBOとシェーダーを使ったもの。
動けばOK
行列はglmを使った。楽ちん。

三角形が回るサンプル。

アプリケーション

// glew32s.libを使う.
#define GLEW_STATIC

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

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>

const int g_WindowWidth = 640;
const int g_WindowHeight = 480;
GLuint g_VBO = 0;
GLuint g_Indices = 0;
GLFWwindow* g_Window = NULL;

glm::mat4 g_World;
glm::mat4 g_View;
glm::mat4 g_Proj;

float g_RotZ = 0.0f;

void printLog(GLuint obj)
{
	int infologLength = 0;
	int maxLength = 0;

	if(glIsShader(obj)) {
		glGetShaderiv(obj, GL_INFO_LOG_LENGTH, &maxLength);
	}
	else {
		glGetProgramiv(obj, GL_INFO_LOG_LENGTH, &maxLength);
	}

	char* infoLog = new char[maxLength];

	if(glIsShader(obj)) {
		glGetShaderInfoLog(obj, maxLength, &infologLength, infoLog);
	}
	else {
		glGetProgramInfoLog(obj, maxLength, &infologLength, infoLog);
	}

	if(infologLength > 0) {
		printf("%s\n", infoLog);
	}

	delete [] infoLog;
}

char* file2string(const char* path)
{
	FILE* fd = fopen(path, "r");
	if(!fd) {
		fprintf(stderr, "Can't open file '%s' for reading\n", path);
		return NULL;
	}

	fseek(fd, 0, SEEK_END);
	long len = ftell(fd);

	printf("File '%s' is %ld long\n", path, len);

	fseek(fd, 0, SEEK_SET);
	
	char* str = (char*)malloc(len * sizeof(char));
	if(!str) {
		fprintf(stderr, "Can't malloc, space for '%s'\n", path);
		return NULL;
	}

	long r = fread(str, sizeof(char), len, fd);
	str[r-1] = '\0';

	fclose(fd);

	return str;
}

int main()
{
	// 初期化.
	if(!glfwInit()) {
		exit(EXIT_FAILURE);
	}
	g_Window = glfwCreateWindow(g_WindowWidth, g_WindowHeight, "Test", NULL, NULL);
	if(!g_Window) {
		glfwTerminate();
		exit(EXIT_FAILURE);
	}
	glfwMakeContextCurrent(g_Window);

	GLenum err = glewInit();
	if(err != GLEW_OK) {
		glfwTerminate();
		exit(EXIT_FAILURE);
	}

	// カメラ設定.
	float ratio = float(g_WindowWidth)/float(g_WindowHeight);
	g_Proj = glm::perspective(30.0f, ratio, 1.f, 50.f);
	g_View = glm::lookAt(glm::vec3(0, 0, 10), glm::vec3(0,0,0), glm::vec3(0,1,0));

	// ジオメトリ設定.
	GLfloat vertexBuffer [] = { 0, 2, 0, -2, -2, 0, 2, -2, 0 };
	GLubyte indexBuffer[] = { 0, 1, 2 };

	glGenBuffers(1, &g_VBO);
	glGenBuffers(1, &g_Indices);

	glBindBuffer(GL_ARRAY_BUFFER, g_VBO);
	glBufferData(GL_ARRAY_BUFFER, sizeof(vertexBuffer), vertexBuffer, GL_STATIC_DRAW);

	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_Indices);
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indexBuffer), indexBuffer, GL_STATIC_DRAW);

	// シェーダー.
	char* src_vs = file2string("vertex.vert");
	char* src_fs = file2string("fragment.frag");

	GLuint vs, fs, sp;

	vs = glCreateShader(GL_VERTEX_SHADER);
	glShaderSource(vs, 1, (const GLchar**)&src_vs, NULL);
	glCompileShader(vs);
	printLog(vs);

	fs = glCreateShader(GL_FRAGMENT_SHADER);
	glShaderSource(fs, 1, (const GLchar**)&src_fs, NULL);
	glCompileShader(fs);
	printLog(fs);

	free(src_vs);
	free(src_fs);

	sp = glCreateProgram();
	glAttachShader(sp, vs);
	glAttachShader(sp, fs);
	glBindFragDataLocation(sp, 0, "outColor");
	glLinkProgram(sp);
	printLog(sp);

	glUseProgram(sp);

	GLint sp_pos = glGetAttribLocation(sp, "pos");

	GLint sp_world = glGetUniformLocation(sp, "world");
	GLint sp_view = glGetUniformLocation(sp, "view");
	GLint sp_proj = glGetUniformLocation(sp, "proj");

	// メインループ.
	while(!glfwWindowShouldClose(g_Window)) {

		if(glfwGetKey(g_Window, GLFW_KEY_ESCAPE) == GLFW_PRESS) {
			glfwSetWindowShouldClose(g_Window, GL_TRUE);
		}

		glViewport(0, 0, g_WindowWidth, g_WindowHeight);
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
		glm::mat4 identity(1);
		g_World = glm::rotate(identity, g_RotZ, glm::vec3(0, 0, 1));
		glColor3f(1, 0, 0);

		g_RotZ += 0.5f;

		glBindBuffer(GL_ARRAY_BUFFER, g_VBO);
		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_Indices);

		// ユニフォーム.
		glUniformMatrix4fv(sp_world, 1, GL_FALSE, glm::value_ptr(g_World));
		glUniformMatrix4fv(sp_view, 1, GL_FALSE, glm::value_ptr(g_View));
		glUniformMatrix4fv(sp_proj, 1, GL_FALSE, glm::value_ptr(g_Proj));

		glEnableVertexAttribArray(0);
		glVertexAttribPointer(sp_pos, 3, GL_FLOAT, GL_FALSE, sizeof(float)*3, 0);
		glEnableVertexAttribArray(sp_pos);
		glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_BYTE, 0);
		glDisableVertexAttribArray(sp_pos);

		glfwSwapBuffers(g_Window);

		glfwPollEvents();
	}

	// 破棄.
	glDeleteBuffers(1, &g_VBO);
	glDeleteBuffers(1, &g_Indices);

	glfwDestroyWindow(g_Window);

	// 終了処理.
	glfwTerminate();
	return 0;
}

頂点シェーダー

#version 140

uniform mat4 world;
uniform mat4 view;
uniform mat4 proj;

in vec3 pos;

void main()
{
	gl_Position = proj * view * world * vec4(pos, 1.0);
}

フラグメントシェーダー

#version 140

out vec4 outColor;

void main()
{
	outColor = vec4(0.0, 1.0, 0.0, 1.0);
}