Quellcode durchsuchen

GL geometry shaders with layered readback

master
Brian Ho vor 5 Jahren
Commit
660c9d51e6
8 geänderte Dateien mit 383 neuen und 0 gelöschten Zeilen
  1. 2
    0
      .gitignore
  2. 74
    0
      Makefile
  3. 13
    0
      blit.frag
  4. 31
    0
      blit.vert
  5. 235
    0
      geometry.cc
  6. 8
    0
      geometry.frag
  7. 12
    0
      geometry.geom
  8. 8
    0
      geometry.vert

+ 2
- 0
.gitignore Datei anzeigen

@@ -0,0 +1,2 @@
occlusion
occlusion.png

+ 74
- 0
Makefile Datei anzeigen

@@ -0,0 +1,74 @@
TRACE = False
ifeq ($(target),$(filter $(target), cheza cheza-trace))
CXX = /usr/bin/armv7a-cros-linux-gnueabihf-clang++
CC = /usr/bin/armv7a-cros-linux-gnueabihf-clang
SYSROOT = /build/cheza
SSH_DUT = cheza-lab
TARGET = cheza
ifeq ($(target), cheza-trace)
TRACE = True
endif
else ifeq ($(target), atlas)
CXX = /usr/bin/x86_64-cros-linux-gnu-clang++
CC = /usr/bin/x86_64-cros-linux-gnu-clang
SYSROOT = /build/atlas
SSH_DUT = atlas
else ifeq ($(target), local)
CXX = clang++
CC = clang
else
CXX = INVALID
CC = INVALID
endif

SUBDIR = "geometry-gl/"
NAME = geometry
CFLAGS = -std=c++17 --sysroot="$(SYSROOT)" -Wall
LDFLAGS = -lEGL -lGLESv2 -lpng

all: build deploy run

build: check
@echo Building...
@$(CXX) $(CFLAGS) -o ${NAME} ${NAME}.cc $(LDFLAGS)

deploy: check
ifneq ($(target), local)
@echo Deploying to $(SSH_DUT)...
@scp ${NAME}.vert $(SSH_DUT):~/${SUBDIR}${NAME}.vert
@scp ${NAME}.geom $(SSH_DUT):~/${SUBDIR}${NAME}.geom
@scp ${NAME}.frag $(SSH_DUT):~/${SUBDIR}${NAME}.frag
@scp blit.vert $(SSH_DUT):~/${SUBDIR}blit.vert
@scp blit.frag $(SSH_DUT):~/${SUBDIR}blit.frag
@scp ${NAME} $(SSH_DUT):~/${SUBDIR}
endif

run: check
ifneq ($(TARGET), local)
@echo Running on $(SSH_DUT)...
ifeq ($(TRACE), True)
@ssh -tt $(SSH_DUT) "~/trace.sh 'cd ~/${SUBDIR} && ./${NAME}'"
@echo Copying artifacts back to local device...
@scp $(SSH_DUT):~/${SUBDIR}/${NAME}.png .
@scp $(SSH_DUT):/tmp/trace.rd .
else
@ssh -tt $(SSH_DUT) 'cd ~/${SUBDIR} && ./${NAME}'
@echo Copying artifacts back to local device...
@scp $(SSH_DUT):~/${SUBDIR}/${NAME}.png .
endif
else
@echo Running locally...
@./$(NAME)
endif

clean: check
@rm -f ${NAME} ${NAME}.png
ifneq ($(target), local)
@ssh $(SSH_DUT) 'rm -f ~/${SUBDIR}${NAME} ~/${SUBDIR}${NAME}.png \
~/${SUBDIR}${NAME}.vert ~/${SUBDIR}${NAME}.frag ~/${SUBDIR}${NAME}.geom'
endif

check:
ifeq ($(CXX), INVALID)
$(error $$target must be one of [atlas, cheza, cheza-trace, local] )
endif

+ 13
- 0
blit.frag Datei anzeigen

@@ -0,0 +1,13 @@
#version 320 es
precision mediump float;
precision mediump sampler2DArray;

layout(location = 0) in vec2 uv;

layout(location = 0) out vec4 outColor;

uniform sampler2DArray image;

void main (void) {
outColor = texture(image, vec3(uv, 0 /* layer */));
}

+ 31
- 0
blit.vert Datei anzeigen

@@ -0,0 +1,31 @@
#version 320 es
precision mediump float;

layout(location = 0) in vec3 inPosition;

layout(location = 0) out vec2 uv;

vec2 uvs[6] = vec2[](
vec2(0.0, 1.0),
vec2(1.0, 0.0),
vec2(0.0, 0.0),

vec2(1.0, 1.0),
vec2(1.0, 0.0),
vec2(0.0, 1.0)
);

vec2 positions[6] = vec2[](
vec2(-1.0, -1.0), // top left
vec2(1.0, 1.0), // bottom right
vec2(-1.0, 1.0), // bottom left

vec2(1.0, -1.0), // top right
vec2(1.0, 1.0), // bottom right
vec2(-1.0, -1.0) // top left
);

void main() {
gl_Position = vec4(positions[gl_VertexID], 0.0, 1.0);
uv = uvs[gl_VertexID];
}

+ 235
- 0
geometry.cc Datei anzeigen

@@ -0,0 +1,235 @@
#include <png.h>
#include <EGL/egl.h>
#include <GL/gl.h>
#include <GL/glext.h>
#include <GLES3/gl32.h>

#include <fstream>
#include <iostream>
#include <sstream>
#include <string>

const uint32_t kWidth = 255;
const uint32_t kHeight = 255;
const uint32_t kLayers = 10;
const std::string kVertexShaderPath = "geometry.vert";
const std::string kGeometryShaderPath = "geometry.geom";
const std::string kFragmentShaderPath = "geometry.frag";

const std::string kBlitVertexPath = "blit.vert";
const std::string kBlitFragmentPath = "blit.frag";

EGLDisplay display;
EGLContext context;
GLuint program;

#define ERROR(message) \
std::cerr << message << std::endl; \
std::exit(EXIT_FAILURE)

void InitializeEGL() {
display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
eglInitialize(display, nullptr, nullptr);
eglBindAPI(EGL_OPENGL_ES_API);

const EGLint config_attribs[] = {
EGL_SURFACE_TYPE, EGL_DONT_CARE,
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
EGL_NONE };
EGLConfig egl_config;
EGLint num_configs;
if (!eglChooseConfig(display, config_attribs, &egl_config, 1, &num_configs)) {
ERROR("Unable to choose EGL config");
}

const EGLint context_attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
context = eglCreateContext(display, egl_config, EGL_NO_CONTEXT, context_attribs);
if (context == EGL_NO_CONTEXT) {
ERROR("Failed to create GLES context");
}

if (!eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, context)) {
ERROR("Failed to make GLES context current");
}
std::cout << glGetString(GL_VERSION) << std::endl;
}

void SetUpLayeredFramebuffer(GLuint layered_texture) {
glBindTexture(GL_TEXTURE_2D_ARRAY, layered_texture);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, kWidth, kHeight, kLayers, 0,
GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
glBindTexture(GL_TEXTURE_2D_ARRAY, 0);

GLuint framebuffer;
glGenFramebuffers(1, &framebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, layered_texture, 0);
}

void SetUpBasicFramebuffer() {
GLuint color_buffer;
glGenRenderbuffers(1, &color_buffer);
glBindRenderbuffer(GL_RENDERBUFFER, color_buffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, kWidth, kHeight);

GLuint framebuffer;
glGenFramebuffers(1, &framebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, color_buffer);
}

GLuint CompileShader(GLenum type, std::string path) {
std::ifstream fstream(path);
if (!fstream) {
ERROR("Unable to read shader: " << path);
}
std::stringstream buffer;
buffer << fstream.rdbuf();
// TODO(brkho): Read the shader source in more intelligently.
std::string shader_source_tmp = buffer.str();
const char* shader_source = shader_source_tmp.c_str();

GLuint shader = glCreateShader(type);
if (!shader) {
ERROR("Failed to create shader of type: " << type);
}
glShaderSource(shader, 1, &shader_source, nullptr);
glCompileShader(shader);
GLint status;
glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
if (!status) {
GLint log_length;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &log_length);
char shader_log[log_length];
glGetShaderInfoLog(shader, log_length, nullptr, shader_log);
ERROR("Failed to compile shader: " << shader_log);
}
return shader;
}

GLuint CreateProgram() {
GLuint vertex_shader = CompileShader(GL_VERTEX_SHADER, kVertexShaderPath);
GLuint geometry_shader = CompileShader(GL_GEOMETRY_SHADER, kGeometryShaderPath);
GLuint fragment_shader = CompileShader(GL_FRAGMENT_SHADER, kFragmentShaderPath);

GLuint program = glCreateProgram();
if (!program) {
ERROR("Failed to create program");
}
glAttachShader(program, vertex_shader);
glAttachShader(program, geometry_shader);
glAttachShader(program, fragment_shader);
glLinkProgram(program);
GLint status;
glGetProgramiv(program, GL_LINK_STATUS, &status);
if (!status) {
GLint log_length = 0;
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &log_length);
char program_log[log_length];
glGetProgramInfoLog(program, log_length, nullptr, program_log);
ERROR("Failed to link program: " << program_log);
}
glDetachShader(program, vertex_shader);
glDetachShader(program, geometry_shader);
glDetachShader(program, fragment_shader);
glDeleteShader(vertex_shader);
glDeleteShader(geometry_shader);
glDeleteShader(fragment_shader);

return program;
}

GLuint CreateBlitProgram() {
GLuint vertex_shader = CompileShader(GL_VERTEX_SHADER, kBlitVertexPath);
GLuint fragment_shader = CompileShader(GL_FRAGMENT_SHADER, kBlitFragmentPath);

GLuint program = glCreateProgram();
if (!program) {
ERROR("Failed to create program");
}
glAttachShader(program, vertex_shader);
glAttachShader(program, fragment_shader);
glLinkProgram(program);
GLint status;
glGetProgramiv(program, GL_LINK_STATUS, &status);
if (!status) {
GLint log_length = 0;
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &log_length);
char program_log[log_length];
glGetProgramInfoLog(program, log_length, nullptr, program_log);
ERROR("Failed to link program: " << program_log);
}
glDetachShader(program, vertex_shader);
glDetachShader(program, fragment_shader);
glDeleteShader(vertex_shader);
glDeleteShader(fragment_shader);

return program;
}

void Draw(GLuint program) {
glViewport(0, 0, kWidth, kHeight);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);

glUseProgram(program);
glDrawArrays(GL_POINTS, 0, 1);
glFinish();
}

void Blit(GLuint program, GLuint layered_texture) {
glViewport(0, 0, kWidth, kHeight);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D_ARRAY, layered_texture);
glUseProgram(program);
glDrawArrays(GL_TRIANGLES, 0, 6);
glFinish();
}

GLubyte* ReadFramebuffer() {
// TODO(brkho): Maybe use a std::array instead?
GLubyte* pixels = static_cast<GLubyte*>(malloc(kWidth * kHeight * 4));
glReadPixels(0, 0, kWidth, kHeight, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
return pixels;
}

void WriteImage(GLubyte* pixels) {
FILE *f = fopen("geometry.png", "wb");

png_image image_info = {};
image_info.version = PNG_IMAGE_VERSION;
image_info.width = kWidth;
image_info.height = kHeight;
image_info.format = PNG_FORMAT_RGBA;
if (png_image_write_to_stdio(&image_info, f, 0, pixels, kWidth * 4, nullptr) == 0) {
ERROR("Error writing PNG: " << image_info.message);
}

fclose(f);
}

int main() {
InitializeEGL();
GLuint layered_texture;
glGenTextures(1, &layered_texture);
SetUpLayeredFramebuffer(layered_texture);
GLuint program = CreateProgram();
Draw(program);

SetUpBasicFramebuffer();
GLuint blit_program = CreateBlitProgram();
Blit(blit_program, layered_texture);

GLubyte* pixels = ReadFramebuffer();
WriteImage(pixels);

eglMakeCurrent(display, EGL_NO_SURFACE,EGL_NO_SURFACE, EGL_NO_CONTEXT);
eglDestroyContext(display, context);
eglTerminate(display);
return EXIT_SUCCESS;
}

+ 8
- 0
geometry.frag Datei anzeigen

@@ -0,0 +1,8 @@
#version 320 es
precision mediump float;

layout(location = 0) out vec4 outColor;

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

+ 12
- 0
geometry.geom Datei anzeigen

@@ -0,0 +1,12 @@
#version 320 es
precision mediump float;

layout (points) in;
layout (points, max_vertices=1) out;

void main() {
gl_Position = gl_in[0].gl_Position + vec4(0.2, 0.0, 0.0, 0.0);
gl_Layer = 8;
EmitVertex();
EndPrimitive();
}

+ 8
- 0
geometry.vert Datei anzeigen

@@ -0,0 +1,8 @@
#version 320 es
precision mediump float;

layout(location = 0) in vec3 inPosition;

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

Laden…
Abbrechen
Speichern