- 여러 쉐이더에서 공유되는 특별한 변수 타입
- 버퍼 객체에 의해 채워진다.
- 버퍼에 저장된 값을 증가시키거나 감소시키며, Atomic 한 특징이 있다.
- 쉐이더에서 동시에 호출하는 경우 Atomic은 보장되지만, 연산이 수행되는 순서는 보장되지 않으므로 특정 값을 받을 것이라고 기대하면 안된다.
- 버퍼 바인딩 인덱스 및 버퍼 내 오프셋은 binding 및 offset 레이아웃 지시어로 설정할 수 있다.
- 선언
- layout (binding = 3, offset = 8) uniform atomic_unit my_variable;
- binding: 어토믹 카운터 바인딩 포인트
- offset: 버퍼 내 오프셋
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 | #include "OpenGL.h" #ifdef EX5_20 GLuint program; GLuint buffer; int getWindowWidth() { return 800; } int getWindowHeight() { return 600; } void onAwake() { static const char * vs_source[] = { "#version 430 core \n" " \n" "layout (binding = 0) uniform area_block \n" "{ \n" " uint counter_value; \n" "}; \n" " \n" "out vec4 color; \n" " \n" "uniform float max_area; \n" " \n" "void main(void) \n" "{ \n" " float brightness = clamp(float(counter_value) / max_area, \n" " 0.0, 1.0); \n" " color = vec4(brightness, brightness, brightness, 1.0); \n" "} \n" }; static const char * fs_source[] = { "#version 430 core \n" " \n" "layout (binding = 0, offset = 0) uniform atomic_uint area; \n" " \n" "void main(void) \n" "{ \n" " atomicCounterIncrement(area); \n" "} \n" }; program = glCreateProgram(); GLuint fs = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(fs, 1, fs_source, NULL); glCompileShader(fs); GLuint vs = glCreateShader(GL_VERTEX_SHADER); glShaderSource(vs, 1, vs_source, NULL); glCompileShader(vs); CheckShaderCompileError(fs); CheckShaderCompileError(vs); glAttachShader(program, vs); glAttachShader(program, fs); glLinkProgram(program); glGenBuffers(1, &buffer); glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, buffer); glBufferData(GL_ATOMIC_COUNTER_BUFFER, 16 * sizeof(GLuint), NULL, GL_DYNAMIC_COPY); glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 3, buffer); const GLuint zero = 0; glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, buffer); // 방법 1 - glBufferSubData를 사용하여 어토믹 카운터를 리셋한다. glBufferSubData(GL_ATOMIC_COUNTER_BUFFER, 2 * sizeof(GLuint), sizeof(GLuint), &zero); // 방법 2 - 버퍼를 매핑하여 직접 값을 쓴다 //GLuint *data = (GLuint *)glMapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, 16 * sizeof(GLuint), GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT); //data[2] = 0; //glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER); //// 방법 3 - glCelarBufferSubData를 사용한다. //glClearBufferSubData(GL_ATOMIC_COUNTER_BUFFER, // GL_R32UI, // 2 * sizeof(GLuint), // sizeof(GLuint), // GL_RED_INTEGER, GL_UNSIGNED_INT, &zero); } void onUpdate(double current_time) { } void onShutdown() { glDeleteProgram(program); glDeleteBuffers(1, &buffer); } #endif | cs |
댓글 없음:
댓글 쓰기