summaryrefslogtreecommitdiffstats
path: root/fiz/naloga/gl/helmholtz.c
blob: 5f8f44d39a6a22f1d87a8bbd5b893c25ba6ff123 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <GL/glxew.h>
#include <GLFW/glfw3.h>

#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
extern char _binary_vertex_glsl_start[];
extern char _binary_vertex_glsl_end[];
extern char _binary_fragment_glsl_start[];
extern char _binary_fragment_glsl_end[];
void error_callback (int error, const char * description) {
	fprintf(stderr, "error_callback: %s, error == %d\n", description, error);
}
void key_callback (GLFWwindow * okno, int tipka, int koda, int dejanje, int modifikatorji) {
	fprintf(stderr, "tipka %d, koda %d, dejanje %d, modifikatorji %d, okno %p\n",
			tipka, koda, dejanje, modifikatorji, (void *) okno);
}
int main (void) {
	GLint vertex_len = _binary_vertex_glsl_end - _binary_vertex_glsl_start;
	GLint fragment_len = _binary_fragment_glsl_end - _binary_fragment_glsl_start;
	if (!glfwInit()) {
		fprintf(stderr, "glfwInit failed\n");
		return 1;
	}
	glfwSetErrorCallback(error_callback);
	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 1);
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 4);
	// glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // forward compat is ogl 3.0+
	GLFWwindow * okno = glfwCreateWindow(800, 600, "okno", NULL, NULL);
	if (!okno) {
		fprintf(stderr, "glfwCreateWindow failed\n");
		glfwTerminate();
		return 2;
	}
	glfwMakeContextCurrent(okno);
	GLenum err = glewInit();
	if (err != GLEW_OK) {
		fprintf(stderr, "glewInit failed: %s\n", glewGetErrorString(err));
		return 3;
	}
	glfwSwapInterval(1); // vsync
	glfwSetKeyCallback(okno, key_callback);
	GLuint program = glCreateProgram();
	float points[] = {
		-1.0f, 1.0f, -1.0f,
		-1.0f, -1.0f, -1.0f,
		1.0f, -1.0f, -1.0f,
		1.0f, -1.0f, -1.0f,
		1.0f, 1.0f, -1.0f,
		-1.0f, 1.0f, -1.0f
	};
	// <black box>
	GLuint points_vbo, vao;
	glGenBuffers(1, &points_vbo);
	glBindBuffer(GL_ARRAY_BUFFER, points_vbo);
	glBufferData(GL_ARRAY_BUFFER, sizeof points, points, GL_STATIC_DRAW);
	glGenVertexArrays(1, &vao);
	glBindVertexArray(vao);
	glEnableVertexAttribArray(0);
	glBindBuffer(GL_ARRAY_BUFFER, points_vbo);
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
	// </black box>
	const char * vertex = _binary_vertex_glsl_start;
	const char * fragment = _binary_fragment_glsl_start;
#define DO_SHADER(whi, WHI) \
	GLuint whi##_shader = glCreateShader(GL_##WHI##_SHADER); \
	glShaderSource(whi##_shader, 1, &whi, &whi##_len); \
	glCompileShader(whi##_shader); \
	GLint whi##_success = 0; \
	glGetShaderiv(whi##_shader, GL_COMPILE_STATUS, &whi##_success); \
	if (whi##_success == GL_FALSE) { \
		GLint logSize = 0; \
		glGetShaderiv(whi##_shader, GL_INFO_LOG_LENGTH, &logSize); \
		char infoLog[logSize]; \
		glGetShaderInfoLog(whi##_shader, logSize, &logSize, infoLog); \
		fprintf(stderr, "prevod shaderja ni uspel. dnevnik:\n%s\n", infoLog); \
		glDeleteShader(whi##_shader); \
		return 4; \
	} \
	glAttachShader(program, whi##_shader);
	DO_SHADER(vertex, VERTEX);
	DO_SHADER(fragment, FRAGMENT);
	// <black box>
	glBindAttribLocation(program, 0, "vertex_position");
	// </black box>
	glLinkProgram(program);
	GLint isLinked = 0;
	glGetProgramiv(program, GL_LINK_STATUS, &isLinked);
	if (isLinked == GL_FALSE) {
		GLint logSize = 0;
		glGetProgramiv(program, GL_INFO_LOG_LENGTH, &logSize);
		char infoLog[logSize];
		glGetProgramInfoLog(program, logSize, &logSize, infoLog);
		fprintf(stderr, "linkanje programa ni uspelo. dnevnik:\n%s\n", infoLog);
		glDeleteShader(vertex_shader);
		glDeleteShader(fragment_shader);
		glDeleteProgram(program);
		return 5;
	}
	// glDetachShader(program, vertex_shader);
	// glDetachShader(program, fragment_shader);
	// glDeleteShader(fragment_shader); // testiraj, mogoče se to sme
	// glDeleteShader(vertex_shader);
	GLuint timeI = glGetUniformLocation(program, "time");
	GLuint optI = glGetUniformLocation(program, "OPTIONS");
	uint32_t opts = 123456;
	glClearColor(0.1, 0.2, 0.3, 1);
	unsigned frame = 0;
	getchar(); // da vmes odpremo okno v floating načinu s pravilno velikostjo
	while (!glfwWindowShouldClose(okno)) {
		int w, h;
		glfwGetFramebufferSize(okno, &w, &h);
		glViewport(0, 0, w, h);
		glClear(GL_COLOR_BUFFER_BIT);
		glUseProgram(program); // testiraj, mogoče se to sme dat iz loopa gor
		glUniform1f(timeI, (float) frame/60);
		glUniform1i(optI, opts++);
		glBindVertexArray(vao);
		glDrawArrays(GL_TRIANGLES, 0, 6 /* dva triangla po 3 */);
		glfwSwapBuffers(okno);
		glfwPollEvents(); // wait / poll
		frame++;
		char fn[25];
		sprintf(fn, "animacija%04d.ppm", frame);
		int fd;
		if ((fd = open(fn, O_CREAT | O_RDWR, 00664)) == -1) {
			perror("open");
			abort();
		}
		if (ftruncate(fd, 128+w*h*3) == -1) {
			perror("ftruncate");
			abort();
		}
		void * p;
		if ((p = mmap(NULL, 128+w*h*3, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0)) == MAP_FAILED) {
			perror("mmap");
			abort();
		}
		sprintf(p, "P6\n\n%57d\n%57d\n255\n", w, h);
		glReadPixels(0, 0, w, h, GL_RGB, GL_UNSIGNED_BYTE, (unsigned char *) p + 128);
		if (munmap(p, 128+w*h*3) == -1) {
			perror("munmap");
			abort();
		}
		if (close(fd) == -1) {
			perror("close");
			abort();
		}
	}
	glfwDestroyWindow(okno);
	glfwTerminate();
	return 0;
}