buffers.cc (5596B)
1 /* Copyright 2013 Brian Swetland <swetland@frotz.net> 2 * 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #include <stdio.h> 17 #include <stdlib.h> 18 19 #include "app.h" 20 #include "util.h" 21 22 static unsigned vattr_type(unsigned type) { 23 switch (type) { 24 case SRC_INT8: return GL_BYTE; 25 case SRC_UINT8: return GL_UNSIGNED_BYTE; 26 case SRC_INT16: return GL_SHORT; 27 case SRC_UINT16: return GL_UNSIGNED_SHORT; 28 case SRC_INT32: return GL_INT; 29 case SRC_UINT32: return GL_UNSIGNED_INT; 30 case SRC_FLOAT: return GL_FLOAT; 31 default: return GL_FLOAT; 32 } 33 } 34 35 #define OFF2PTR(off) (((char*) NULL) + off) 36 37 void VertexAttributes::init(VertexAttrDesc *desc, VertexBuffer **data, unsigned count) { 38 unsigned id = 0, n; 39 glGenVertexArrays(1, &vao); 40 glBindVertexArray(vao); 41 for (n = 0; n < count; n++) { 42 if (data && (data[n]->id != id)) { 43 id = data[n]->id; 44 glBindBuffer(GL_ARRAY_BUFFER, id); 45 } 46 switch (desc->dst_type) { 47 case DST_FLOAT: 48 glVertexAttribPointer(desc->index, desc->count, 49 vattr_type(desc->src_type), GL_FALSE, desc->stride, 50 OFF2PTR(desc->offset)); 51 break; 52 case DST_NORMALIZED: 53 glVertexAttribPointer(desc->index, desc->count, 54 vattr_type(desc->src_type), GL_TRUE, desc->stride, 55 OFF2PTR(desc->offset)); 56 break; 57 case DST_INTEGER: 58 glVertexAttribIPointer(desc->index, desc->count, 59 vattr_type(desc->src_type), desc->stride, 60 OFF2PTR(desc->offset)); 61 break; 62 } 63 glVertexAttribDivisor(desc->index, desc->divisor); 64 glEnableVertexAttribArray(desc->index); 65 desc++; 66 } 67 } 68 69 70 void VertexBuffer::load(void *data, unsigned size) { 71 if (id == 0) 72 glGenBuffers(1, &id); 73 glBindBuffer(GL_ARRAY_BUFFER, id); 74 glBufferData(GL_ARRAY_BUFFER, size, data, GL_STATIC_DRAW); 75 sz = size; 76 } 77 78 void IndexBuffer::load(void *data, unsigned size) { 79 if (id == 0) 80 glGenBuffers(1, &id); 81 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, id); 82 glBufferData(GL_ELEMENT_ARRAY_BUFFER, size, data, GL_STATIC_DRAW); 83 sz = size; 84 } 85 86 void UniformBuffer::load(void *data, unsigned size) { 87 if (id == 0) 88 glGenBuffers(1, &id); 89 glBindBuffer(GL_UNIFORM_BUFFER, id); 90 glBufferData(GL_UNIFORM_BUFFER, size, data, GL_STATIC_DRAW); 91 sz = size; 92 } 93 94 int Texture2D::load(const char *fn, int options) { 95 void *data; 96 unsigned dw, dh; 97 int r; 98 if (!(data = load_png_rgba(fn, &dw, &dh, options))) 99 return error("cannot load '%s'", fn); 100 r = load(data, dw, dh, options); 101 free(data); 102 return r; 103 } 104 105 int Texture2D::load(void *data, unsigned w, unsigned h, int options) { 106 if (id == 0) 107 glGenTextures(1, &id); 108 109 /* GL 3.x guarantees at least 16 texture units. We'll use */ 110 /* unit 15 for load operations to avoid stepping on other */ 111 /* state that might be important. */ 112 glActiveTexture(GL_TEXTURE0 + 15); 113 114 glBindTexture(GL_TEXTURE_2D, id); 115 if (!(options & OPT_TEX2D_GEN_MIPMAP)) { 116 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); 117 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); 118 } 119 if (options & OPT_TEX2D_GRAY) { 120 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, 121 GL_RED, GL_UNSIGNED_BYTE, data); 122 } else { 123 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, 124 GL_RGBA, GL_UNSIGNED_BYTE, data); 125 } 126 if (options & OPT_TEX2D_GEN_MIPMAP) { 127 glGenerateMipmap(GL_TEXTURE_2D); 128 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); 129 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 130 } else { 131 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 132 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 133 } 134 width = w; 135 height = h; 136 return 0; 137 } 138 139 int Texture2D::createRGBA(unsigned w, unsigned h) { 140 if (id) 141 glDeleteTextures(1, &id); 142 glGenTextures(1, &id); 143 glActiveTexture(GL_TEXTURE0 + 15); 144 glBindTexture(GL_TEXTURE_2D, id); 145 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); 146 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); 147 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); 148 width = w; 149 height = h; 150 return 0; 151 } 152 153 void FrameBuffer::init(unsigned w, unsigned h, unsigned _depth) { 154 glGenTextures(1, &txid); 155 glActiveTexture(GL_TEXTURE0 + 15); 156 glBindTexture(GL_TEXTURE_RECTANGLE, txid); 157 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_BASE_LEVEL, 0); 158 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAX_LEVEL, 0); 159 glTexImage2D(GL_TEXTURE_RECTANGLE, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); 160 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 161 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 162 163 if (_depth) { 164 glGenRenderbuffers(1, &depth); 165 glBindRenderbuffer(GL_RENDERBUFFER, depth); 166 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, w, h); 167 glBindRenderbuffer(GL_RENDERBUFFER, 0); 168 } 169 170 glGenFramebuffers(1, &id); 171 glBindFramebuffer(GL_FRAMEBUFFER, id); 172 173 /* color buffer */ 174 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 175 GL_TEXTURE_RECTANGLE, txid, 0); 176 177 /* depth buffer */ 178 if (_depth) { 179 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, 180 GL_RENDERBUFFER, depth); 181 } 182 183 glBindFramebuffer(GL_FRAMEBUFFER, 0); 184 185 width = w; 186 height = h; 187 }