opengl

opengl 시점변환 원근투영 - 하드코딩

현구구 2022. 9. 6. 15:26

 


//배경색 칠하기//////////////////////////////////////////
// sb6.h 헤더 파일을 포함시킨다.
#include <sb7.h>
#include <vmath.h> //수학 함수 해더파일 sin,cos
// sb6::application을 상속받는다.
class my_application : public sb7::application
{
public: //쉐이더 컴파일 과정
	GLuint compile_shaders(void)
	{
		//쉐이더 객체 생성
		GLuint vertex_shader_pung;
		vertex_shader_pung = glCreateShader(GL_VERTEX_SHADER);
		GLuint fragment_shader_pung;
		fragment_shader_pung = glCreateShader(GL_FRAGMENT_SHADER);

		//쉐이더 소스 코드
		const GLchar* vertex_shader_source_pung[] =
		{
			//"#version 430 core\n"
			//"\n"
			//"void main(void)\n"
			//"{\n"
			//"	gl_Position = vec4(0.0, 0.0, 0.5, 1.0);\n" //이게 중앙이래
			//"}\n" //얘는 점 위치

			"#version 430 core\n"
			"\n"

			"layout(location = 0) in vec4 offset;\n"
			"layout(location = 5) in float angle_vs;\n"
			"out vec4 vs_color;\n"
			"void main(void)\n"
			"{\n"
			//점위치 잡아주기===============================
			"	const vec4 vertices[12] = vec4[12](vec4(0.0, 0.0, 0.5, 1.0),\n"
			"		vec4(0.0, 0.5, 0.5, 1.0),\n"
			"		vec4(-0.5, 0.5, 0.5, 1.0),\n"
			"vec4(0.0, 0.0, 0.5, 1.0),\n"
			"vec4(0.5, 0.0, 0.5, 1.0),\n"
			"vec4(0.5, 0.5, 0.5, 1.0),\n"
			"vec4(0.0, 0.0, 0.5, 1.0),\n"
			"vec4(-0.5, 0.0, 0.5, 1.0),\n"
			"vec4(-0.5, -0.5, 0.5, 1.0),\n"
			"vec4(0.0, 0.0, 0.5, 1.0),\n"
			"vec4(0.0, -0.5, 0.5, 1.0),\n"
			"vec4(0.5, -0.5, 0.5, 1.0));\n"
			//회전행렬=======================
			"mat4 m1;\n"
			"m1[0] = vec4(cos(angle_vs),sin(angle_vs),0.0,0.0);\n"
			"m1[1] = vec4(-sin(angle_vs),cos(angle_vs),0.0,0.0);\n"
			"m1[2] = vec4(0.0,0.0,1.0,0.0);\n"
			"m1[3] = vec4(0.0,0.0,0.0,1.0);\n"
			//
			//lookat 매트릭스===================================
			"vec3 eyePos = vec3(0.4,0.5,0.8);\n"
			"vec3 target = vec3(0.0,0.0,0.5)\n;"
			"vec3 upVec = vec3(0.0,1.0,0.0);\n"
			"vec3 P = eyePos;\n"
			"vec3 D = (P-target)/length((P-target));\n"
			"vec3 R = cross(upVec,D);\n"
			"vec3 U = cross(D,R);\n"
			"mat4 m2;\n"
			"m2[0] = vec4(R[0],U[0],D[0],0.0);\n"
			"m2[1] = vec4(R[1],U[1],D[1],0.0);\n"
			"m2[2] = vec4(R[2],U[2],D[2],0.0);\n"
			"m2[3] = vec4(0.0,0.0,0.0,1.0);\n"
			"mat4 m3;\n"
			"m3[0] = vec4(1.0,0.0,0.0,0.0);\n"
			"m3[1] = vec4(0.0,1.0,0.0,0.0);\n"
			"m3[2] = vec4(0.0,0.0,1.0,0.0);\n"
			"m3[3] = vec4(-P[0],-P[1],-P[2],1.0);\n"
			"mat4 m4;\n"
			"m4 = m2*m3;\n"
			//원근투영 매트릭스======================================
			"mat4 m5;\n"
			"m5[0] = vec4(1.0,0.0,0.0,0.0);\n"
			"m5[1] = vec4(0.0,10/7,0.0,0.0);\n"
			"m5[2] = vec4(0.0,0.0,-10.1/9.9,-1);\n"
			"m5[3] = vec4(0.0,0.0,-2/9.9,0.0);\n"
			//===========점 설정 ===========================
			"	gl_Position = m5*m4*m1*vertices[gl_VertexID];\n" // 오른쪽vertices[gl_VertexID] 점의 위치
			//==========색깔 잡아주기
			"	const vec4 colors[12] = vec4[12](vec4(1.0, 0.0, 0.0, 1.0),\n"
			"		vec4(0.0, 1.0, 0.0, 1.0),\n"
			"		vec4(0.0, 0.0, 1.0, 1.0),\n"
			"		vec4(1.0, 0.0, 0.0, 1.0),\n"
			"		vec4(0.0, 1.0, 0.0, 1.0),\n"
			"		vec4(0.0, 0.0, 1.0, 1.0),\n"
			"		vec4(1.0, 0.0, 0.0, 1.0),\n"
			"		vec4(0.0, 1.0, 0.0, 1.0),\n"
			"		vec4(0.0, 0.0, 1.0, 1.0),\n"
			"		vec4(1.0, 0.0, 0.0, 1.0),\n"
			"		vec4(0.0, 1.0, 0.0, 1.0),\n"
			"		vec4(0.0, 0.0, 1.0, 1.0));\n"
			"	vs_color = colors[gl_VertexID]+offset;\n"
			"}\n"
		};

			//프래그먼트 소스코드
		const GLchar * fragment_shdaer_source_pung[] =
		{
			"#version 430 core\n"
			"in vec4 vs_color;\n"
			"out vec4 color;\n"
			"void main(void)\n"
			"{\n"
			"	color = vs_color;\n"
			"}\n"
		};
		//쉐이더 소스코드 쉐이더 객체로 전달
		glShaderSource(vertex_shader_pung, 1, vertex_shader_source_pung, NULL);
		glShaderSource(fragment_shader_pung, 1, fragment_shdaer_source_pung, NULL);
		//쉐이더 객체의 소스 코드 컴파일 mack
		glCompileShader(vertex_shader_pung);
		glCompileShader(fragment_shader_pung);
		//프로그램 객체 생성
		GLuint program_pung;
		program_pung = glCreateProgram();




		//쉐이더 객체를 프로그램에 어태치 시킴
		glAttachShader(program_pung, vertex_shader_pung);
		glAttachShader(program_pung, fragment_shader_pung);

		//프로그램 객체에 어태치 시킨 쉐이더 객채들을 링크함
		glLinkProgram(program_pung);

		//쉐이더 객체들을 삭제한다
		glDeleteShader(vertex_shader_pung);
		glDeleteShader(fragment_shader_pung);

		return program_pung; //program 을 리턴해줌

	}
	GLuint compile_shaders_mack(void)
	{
		//쉐이더 객체 생성
		GLuint vertex_shader_mack;
		vertex_shader_mack = glCreateShader(GL_VERTEX_SHADER);
		GLuint fragment_shader_mack;
		fragment_shader_mack = glCreateShader(GL_FRAGMENT_SHADER);

		//쉐이더 소스 코드
		const GLchar* vertex_shader_source_mack[] =
		{

			"#version 430 core\n"
			"\n"

			"void main(void)\n"
			"{\n"
			"	const vec4 vertices[6] = vec4[6](vec4(-0.01, 0.0, 0.5, 1.0),\n"
			"		vec4(-0.01, -1, 0.5, 1.0),\n"
			"		vec4(0.01, -1.0, 0.5, 1.0),\n"
			"vec4(-0.01, 0.0, 0.5, 1.0),\n"
			"vec4(0.01, 0, 0.5, 1.0),\n"
			"vec4(0.01, -1.0, 0.5, 1.0));\n"
			//lookat 매트릭스==================
			"vec3 eyePos = vec3(0.2,0.3,0.8);\n"
			"vec3 target = vec3(0.0,0.0,0.5)\n;"
			"vec3 upVec = vec3(0.0,1.0,0.0);\n"
			"vec3 P = eyePos;\n"
			"vec3 D = (P-target)/length((P-target));\n"
			"vec3 R = cross(upVec,D);\n"
			"vec3 U = cross(D,R);\n"
			"mat4 m2;\n"
			"m2[0] = vec4(R[0],U[0],D[0],0.0);\n"
			"m2[1] = vec4(R[1],U[1],D[1],0.0);\n"
			"m2[2] = vec4(R[2],U[2],D[2],0.0);\n"
			"m2[3] = vec4(0.0,0.0,0.0,1.0);\n"
			"mat4 m3;\n"
			"m3[0] = vec4(1.0,0.0,0.0,0.0);\n"
			"m3[1] = vec4(0.0,1.0,0.0,0.0);\n"
			"m3[2] = vec4(0.0,0.0,1.0,0.0);\n"
			"m3[3] = vec4(-P[0],-P[1],-P[2],1.0);\n"
			"mat4 m4;\n"
			"m4 = m2*m3;\n"
			//원근투영 매트릭스==========================================
			"mat4 m5;\n"
			"m5[0] = vec4(1.0,0.0,0.0,0.0);\n"
			"m5[1] = vec4(0.0,10/7,0.0,0.0);\n"
			"m5[2] = vec4(0.0,0.0,-10.1/9.9,-1);\n"
			"m5[3] = vec4(0.0,0.0,-2/9.9,0.0);\n"
			"	gl_Position = m5*m4*vertices[gl_VertexID];\n"
			"}\n"
		};

		//프래그먼트 소스코드
		const GLchar* fragment_shdaer_source_mack[] =
		{
			"#version 430 core\n"
			"out vec4 color;\n"
			"void main(void)\n"
			"{\n"
			"	color = vec4(1,1,0,1);\n"
			"}\n"
		};
		//쉐이더 소스코드 쉐이더 객체로 전달
		glShaderSource(vertex_shader_mack, 1, vertex_shader_source_mack, NULL);
		glShaderSource(fragment_shader_mack, 1, fragment_shdaer_source_mack, NULL);
		//쉐이더 객체의 소스 코드 컴파일 mack
		glCompileShader(vertex_shader_mack);
		glCompileShader(fragment_shader_mack);
		//프로그램 객체 생성
		GLuint program_mack;
		program_mack = glCreateProgram();




		//쉐이더 객체를 프로그램에 어태치 시킴
		glAttachShader(program_mack, vertex_shader_mack);
		glAttachShader(program_mack, fragment_shader_mack);

		//프로그램 객체에 어태치 시킨 쉐이더 객채들을 링크함
		glLinkProgram(program_mack);

		//쉐이더 객체들을 삭제한다
		glDeleteShader(vertex_shader_mack);
		glDeleteShader(fragment_shader_mack);

		return program_mack; //program 을 리턴해줌

	}

	virtual void startup() //애플리케이션 초기화 가상함수
	{
		rendering_program = compile_shaders();//쉐이더 및 프로그램 재 컴파일 안하도록 일련의 과정 startup에 저장//리턴값인 program 이 들어옴
		glGenVertexArrays(1, &vertex_array_object);
		glBindVertexArray(vertex_array_object);
		//====================================
		rendering_program_mack = compile_shaders_mack();
		glGenVertexArrays(1, &vertex_array_object_mack);
		glBindVertexArray(vertex_array_object_mack);
	}

	virtual void shutdown()//애플리케이션 종료시 호출되는 함수
	{
		glDeleteVertexArrays(1, &vertex_array_object);
		glDeleteProgram(rendering_program);
		//============================================
		glDeleteVertexArrays(1, &vertex_array_object_mack);
		glDeleteProgram(rendering_program_mack);
	}

	// 렌더링 virtual 함수를 작성해서 오버라이딩한다.
	virtual void render(double currentTime) // = tick함수 무한반복 currentTime -> 1초 / render virtual 로 재정의(override)
	{

		GLfloat attrib[] = { (float)sin(currentTime) * 0.5f, (float)cos(currentTime) * 0.5f, 0.0f, 0.0f };
		glVertexAttrib4fv(0, attrib);//vertax shader 로 넘길 값 index 는 0 
		GLfloat color[] = { 0.0f, 1.0f, 1.0f, 0.0f };
		glVertexAttrib4fv(1, color);
		//===================================================
		const GLfloat black[] = { 0.0f, 0.0f, 0.0f, 1.0f };
		//배경 색깔
		glClearBufferfv(GL_COLOR, 0, black);

		//프로그램 실행 막대=============================

		glUseProgram(rendering_program_mack);
		glDrawArrays(GL_TRIANGLES, 0, 6);
		//===============================================================
		glUseProgram(rendering_program);

		float angle = currentTime;
		glVertexAttrib1f(5, angle);

		glDrawArrays(GL_TRIANGLES, 0, 12); //삼각형 점이 3개 필요
	} //모든 OpenGL 함수는 gl 로 시작 

private:
	GLuint rendering_program;
	GLuint vertex_array_object;

	GLuint rendering_program_mack;
	GLuint vertex_array_object_mack;
};


// DECLARE_MAIN의 하나뿐인 인스턴스
DECLARE_MAIN(my_application) // int main() 대체, class명 삽입

eyepos는 카메라의 위치

target은 오브젝트의 위치

upVec은 카메라의 윗부분이 향하는 방향이다(쉽게 말해 상하 기울기)

그 후 아래와 같은 공식으로 lookat매트릭스를 지정해주면 된다

결과 매트릭스는 m4이다

이는 나중에 render함수에서 하드코딩이 아닌 opengl라이브러리로 더 쉬운방법으로 진행하게된다

원근투영매트릭스 역시 공식을 사용하여 하드코딩하였다 이는 오브젝트와 카메라의 위치가 멀어질수록 작게 보이는 원근투영을 적용하는 것이다

이 역시 나중에 opengl라이브러리로 쉽게 처리하게 된다.

 

'opengl' 카테고리의 다른 글

opengl 텍스처  (0) 2023.01.04
opengl 시점변환 원근투영 - opengl라이브러리  (0) 2022.09.06
opengl 바람개비 회전 - 유니폼 VBO 사용  (0) 2022.09.06
opengl 바람개비 보간  (0) 2022.09.06
opengl 삼각형 보간  (0) 2022.08.25