纹理实现

思想

这个是Cocos2dx的渲染部分的最基本的实现,被我拆分到mac上,但是并不是用的EGLContext,而是搭配glfw,还有soil第三方图形库。

实现

//
// main.cpp
// Moni
//
// Created by staff on 17/1/10.
// Copyright © 2017年 staff. All rights reserved.
// #include <iostream>
#include <string>
#include <cassert>
#include <GL/glew.h>
#include <GLUT/glut.h>
#include <GLFW/glfw3.h>
#include "png.h"
#include "SOIL.h"
#include "CCOPGL.h" #include <unordered_map>
#include "CCVector2.h"
#include "CCVector3.h"
#include "CCVector4.h"
#include "CCMatrix.h"
#include "CCType.h" #define STRINGIFY(A) #A
#include "CCPositionTextureColor.frag"
#include "CCPositionTextureColor.vert" using namespace std; #define MAX_VERTICES_SIZE 65536 //Buffer中一次存储进顶点数据的最大数目
#define MAX_INDICES_SIZE MAX_VERTICES_SIZE * 6 / 4 //前者的索引 #define MATIRIAL_ID_NOT_BATCH 0
#define UNIFORM_MAX_SIZE 7 // Attribute顶点属性变量名字(需要和shader中的对应起来,否则无法传值)
typedef enum {
VERTEX_ATTRIB_POSITION = 0, // 位置
VERTEX_ATTRIB_COLOR, // 颜色
VERTEX_ATTRIB_TEXCOOD // 纹理坐标
} VERTEX_ATTRIB_TYPE; typedef enum {
UNIFORM_P_MATRIX = 0,
UNIFORM_MV_MATRIX,
UNIFORM_MVP_MATRIX, UNIFORM_SAMPLER0,
UNIFORM_SAMPLER1,
UNIFORM_SAMPLER2,
UNIFORM_SAMPLER3,
}VERTEX_UNIFORM_TYPE; // shader中的vertexAttrib
struct VertexAttrib
{
GLuint index; //属性下标,从0开始
GLint size; //数据个数
GLenum type; //数据类型
string name; //顶点着色器的名字
}; // shader中的uniform
struct Uniform
{
GLint location; //属性位置,从0开始
GLint size;
GLenum type;
string name;
}; // 封装Uniform
class UniformValue {
public:
UniformValue();
~UniformValue(); protected:
Uniform _uniform;
}; // 封装VertexAttrib
class VertexAttribValue {
public:
VertexAttribValue();
~VertexAttribValue(); protected:
VertexAttrib _attrib;
}; struct Triangles //三角形
{
V3F_C4B_T2F *verts; //顶点数据
unsigned int* indices;
ssize_t vertCount;
ssize_t indexCount; void outVerts() {
for (ssize_t i = 0; i < vertCount; i++) {
cout << "第" << i + 1 << "个顶点信息" << endl;
cout << "坐标:" << verts[i].vertices.x << "," << verts[i].vertices.y << "," << verts[i].vertices.z << endl;
cout << "颜色:" << verts[i].colors.r << "," << verts[i].colors.g << "," << verts[i].colors.b << endl;
cout << "纹理:" << verts[i].texCoords.u << "," << verts[i].texCoords.v << endl;
}
} void outIndics() {
for (ssize_t i = 0; i < indexCount; i++) {
cout << "第" << i + 1 << "个纹理信息" << endl;
cout << indices[i] << endl;
}
}
}; // 用流读取图片数据的回调函数
typedef struct
{
const unsigned char * data;
ssize_t size;
int offset;
}tImageSource; // 设定attribute值
static const char* ATTRIBUTE_NAME_POSITION = "a_position";
static const char* ATTRIBUTE_NAME_COLOR = "a_color";
static const char* ATTRIBUTE_NAME_TEXCOOD = "a_texCoord"; // 设置统一变量值
static const char* UNIFORM_NAME_P_MATRIX = "CC_PMatrix";
static const char* UNIFORM_NAME_MV_MATRIX = "CC_MVMatrix";
static const char* UNIFORM_NAME_MVP_MATRIX = "CC_MVPMatrix";
static const char* UNIFORM_NAME_SAMPLER0 = "CC_Texture0";
static const char* UNIFORM_NAME_SAMPLER1 = "CC_Texture1";
static const char* UNIFORM_NAME_SAMPLER2 = "CC_Texture2";
static const char* UNIFORM_NAME_SAMPLER3 = "CC_Texture3"; // 用作缓存,暂时不用
const char* SHADER_NAME_POSITION_TEXTURE_COLOR = "ShaderPositionTextureColor"; static const char* DEFAULT_SHADER_UNIFORMS =
"uniform mat4 CC_PMatrix;\n"
"uniform mat4 CC_MVMatrix;\n"
"uniform mat4 CC_MVPMatrix;\n"
"uniform sampler2D CC_Texture0;\n"
"uniform sampler2D CC_Texture1;\n"
"uniform sampler2D CC_Texture2;\n"
"uniform sampler2D CC_Texture3;\n"
"//CC INCLUDES END\n\n"; static unsigned int quadIndices[] = {
0, 1, 2,
1, 2, 3
}; class CCData {
public:
CCData() { } CCData(unsigned char* bytes, ssize_t size) {
_bytes = bytes;
_size = size;
} ~CCData() {
_bytes = NULL;
_size = 0;
} CCData& operator=(const CCData& other) {
copy(other._bytes, other._size);
return *this;
} CCData& operator=(CCData&& other) {
move(other);
return *this;
} // 移动构造函数
void move(CCData& data) {
_bytes = data._bytes;
_size = data._size; data._bytes = NULL;
data._size = 0;
} // 拷贝构造函数
void copy(const unsigned char* bytes, const ssize_t size) {
if (size > 0) {
_size = size;
_bytes = (unsigned char*)malloc(sizeof(unsigned char*) * size);
memcpy(_bytes, bytes, _size);
}
} void fastSet(unsigned char* bytes, const ssize_t size)
{
_bytes = bytes;
_size = size;
} unsigned char* getBytes() {
return _bytes;
} ssize_t getSize() {
return _size;
} protected:
unsigned char* _bytes;
ssize_t _size;
}; class CCSize {
public:
CCSize() { } CCSize(float x, float y) {
_x = x;
_y = y;
} ~CCSize() { } void fastSet(float x, float y) {
_x = x;
_y = y;
} float getX() const {
return _x;
} float getY() const {
return _y;
}
private:
float _x;
float _y;
}; GLuint _triangleVAO;
GLuint _triangleVBO[2]; //默认支持VBO
V3F_C4B_T2F Vertexs[MAX_VERTICES_SIZE]; //绘制的节点信息
GLuint Indices[MAX_INDICES_SIZE]; // 绘制所需的索引信息 unsigned int _filledVertex = 0; //填充的顶点偏移
unsigned int _filledIndex = 0; //填充的索引偏移 Color4F _clearColor; //默认的颜色 GLuint _program; //渲染程序
GLuint _vertexShader; //顶点着色器
GLuint _fragShader; //片元着色器
GLint _uniforms[UNIFORM_MAX_SIZE]; //统一变量
unordered_map<string, Uniform> _uniformsMap; //建立通过名字找到的统一变量
unordered_map<string, VertexAttrib> _verAttribsMap; //建立通过名字找到的顶点属性 // 精灵的属性
GLuint _sp_textureID;
BlendFunc _sp_blend;
Triangles _sp_triangles;
V3F_C4B_T2F_Quad _sp_quad;
Matrix _sp_modelView; CCData _sp_image_data;
CCSize _sp_image_size; Vector2 _sp_position(0, 0); bool _sp_transformUpdated = false; void pngReadCallback(png_structp png_ptr, png_bytep data, png_size_t length)
{
tImageSource* isource = (tImageSource*)png_get_io_ptr(png_ptr); if((int)(isource->offset + length) <= isource->size)
{
memcpy(data, isource->data+isource->offset, length);
isource->offset += length;
}
else
{
png_error(png_ptr, "pngReaderCallback failed");
}
} void reset() {
_clearColor = Color4F::WHITE;
// 清除深度缓存和颜色缓存
glClearColor(_clearColor.r, _clearColor.g, _clearColor.b, _clearColor.a);
glClear(GL_COLOR_BUFFER_BIT);
} void clearShader() {
if (_vertexShader) {
glDeleteShader(_vertexShader);
} if (_fragShader) {
glDeleteShader(_fragShader);
} _vertexShader = _fragShader = 0;
} void handleUniforms() {
// 对uniforms进行初始化
_uniforms[UNIFORM_P_MATRIX] = glGetUniformLocation(_program, UNIFORM_NAME_P_MATRIX);
_uniforms[UNIFORM_MV_MATRIX] = glGetUniformLocation(_program, UNIFORM_NAME_MV_MATRIX);
_uniforms[UNIFORM_MVP_MATRIX] = glGetUniformLocation(_program, UNIFORM_NAME_MVP_MATRIX);
_uniforms[UNIFORM_SAMPLER0] = glGetUniformLocation(_program, UNIFORM_NAME_SAMPLER0);
_uniforms[UNIFORM_SAMPLER1] = glGetUniformLocation(_program, UNIFORM_NAME_SAMPLER1);
_uniforms[UNIFORM_SAMPLER2] = glGetUniformLocation(_program, UNIFORM_NAME_SAMPLER2);
_uniforms[UNIFORM_SAMPLER3] = glGetUniformLocation(_program, UNIFORM_NAME_SAMPLER3);
} void handleVertexAttrib() { GLint active_attrib_count;
GLint length;
// 获取已经激活的属性数量
glGetProgramiv(_program, GL_ACTIVE_ATTRIBUTES, &active_attrib_count);
if (active_attrib_count > 0) {
glGetProgramiv(_program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &length);
VertexAttrib attribute;
if (length > 0) {
GLchar *attribName = (GLchar*) alloca(length + 1);
for (GLint i = 0; i < active_attrib_count; i++) {
glGetActiveAttrib(_program, i, length, nullptr, &attribute.size, &attribute.type, attribName);
}
}
}
else {
GLchar ErrorLog[1024];
glGetProgramInfoLog(_program, sizeof(ErrorLog), NULL, ErrorLog);
cout << "vertex attrib." << ErrorLog << endl;
}
} // 创建program和shader
void initProgramShader(const GLchar* vertexArr, const GLchar* fragArr) {
_program = glCreateProgram();
_vertexShader = _fragShader = 0; _vertexShader = glCreateShader(GL_VERTEX_SHADER);
if (vertexArr != NULL) {
const GLchar *sources[] = {
DEFAULT_SHADER_UNIFORMS,
vertexArr
};
glShaderSource(_vertexShader, sizeof(sources)/sizeof(*sources), sources, NULL);
glCompileShader(_vertexShader);
GLint status;
glGetShaderiv(_vertexShader, GL_COMPILE_STATUS, &status);
if (!status) {
GLint infoLen = 0;
glGetShaderiv(_vertexShader, GL_INFO_LOG_LENGTH, &infoLen);
if (infoLen) {
char* infoLog = static_cast<char *>(malloc(sizeof(char) * infoLen));
glGetShaderInfoLog(_vertexShader, infoLen, NULL, infoLog);
cout << "compile vertex shader wrong..." << infoLog << endl;
}
}
else {
cout << "compile vertex shader success..." << endl;
}
} _fragShader = glCreateShader(GL_FRAGMENT_SHADER);
// 片元着色器中没有指定的精度,所以必须要指定一个精度
if (fragArr != NULL) {
const GLchar *sources[] = {
DEFAULT_SHADER_UNIFORMS,
fragArr
};
glShaderSource(_fragShader, sizeof(sources)/sizeof(*sources), sources, NULL);
glCompileShader(_fragShader);
GLint status;
glGetShaderiv(_fragShader, GL_COMPILE_STATUS, &status);
if (!status) {
GLint infoLen = 0;
glGetShaderiv(_fragShader, GL_INFO_LOG_LENGTH, &infoLen);
if (infoLen) {
char* infoLog = static_cast<char *>(malloc(sizeof(char) * infoLen));
glGetShaderInfoLog(_fragShader, infoLen, NULL, infoLog);
cout << "compile fragment shader wrong..." << infoLog << endl;
}
}
else {
cout << "compile fragment shader success..." << endl;
}
} // 创建和链接程序
if (_vertexShader) {
glAttachShader(_program, _vertexShader);
} if (_fragShader) {
glAttachShader(_program, _fragShader);
} // 验证程序对象(比较慢,不推荐使用)
//glValidateProgram(_program); // 将通用顶点属性索引和指定的属性变量关联起来
// 用来将Program指定的程序对象中的一个用户定义的属性变量和一个通用的顶点属性索引绑定
// 属性数组
static const struct {
const char* attributeName;
VERTEX_ATTRIB_TYPE type;
}
attribute_locations[] = {
{ATTRIBUTE_NAME_POSITION, VERTEX_ATTRIB_POSITION}, //顶点位置
{ATTRIBUTE_NAME_COLOR, VERTEX_ATTRIB_COLOR}, //顶点颜色
{ATTRIBUTE_NAME_TEXCOOD, VERTEX_ATTRIB_TEXCOOD}, //顶点纹理坐标
}; // 把顶点属性索引绑定属性名
for (int i = 0; i < sizeof(attribute_locations)/sizeof(attribute_locations[0]); i++) {
glBindAttribLocation(_program, attribute_locations[i].type, attribute_locations[i].attributeName);
} glLinkProgram(_program); //需要在program创建了以后才可以获取
handleUniforms(); // 已经使用完shader以后,则重置shader
clearShader(); GLint status = GL_TRUE;
glGetProgramiv(_program, GL_LINK_STATUS, &status);
if (status == GL_FALSE) {
cout << "the program link failed." << endl;
glDeleteProgram(_program);
_program = 0;
assert(status == GL_FALSE);
}
else {
cout << "the program link success..." << endl;
} handleVertexAttrib(); } // 初始化图片的数据
bool initWithImageData(const unsigned char * data, ssize_t dataLen) {
#define PNGSIGSIZE 8
bool ret = false;
png_byte header[PNGSIGSIZE] = {0};
png_structp png_ptr = 0;
png_infop info_ptr = 0;
do
{
memcpy(header, data, PNGSIGSIZE); png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
info_ptr = png_create_info_struct(png_ptr); //png_set_read_fn(png_ptr, &imageSource, pngReadCallback); // read png header info
tImageSource imageSource;
imageSource.data = (unsigned char*)data;
imageSource.size = dataLen;
imageSource.offset = 0;
png_set_read_fn(png_ptr, &imageSource, pngReadCallback); // read png file info
png_read_info(png_ptr, info_ptr);
size_t _img_width = png_get_image_width(png_ptr, info_ptr);
size_t _img_height = png_get_image_height(png_ptr, info_ptr); _sp_image_size.fastSet((float)_img_width, (float)_img_height); png_byte bit_depth = png_get_bit_depth(png_ptr, info_ptr);
png_uint_32 color_type = png_get_color_type(png_ptr, info_ptr); if (color_type == PNG_COLOR_TYPE_PALETTE)
{
png_set_palette_to_rgb(png_ptr);
}
if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
{
bit_depth = 8;
png_set_expand_gray_1_2_4_to_8(png_ptr);
}
// reduce images with 16-bit samples to 8 bits
if (bit_depth == 16)
{
png_set_strip_16(png_ptr);
}
// Expanded earlier for grayscale, now take care of palette and rgb
if (bit_depth < 8)
{
png_set_packing(png_ptr);
} png_read_update_info(png_ptr, info_ptr);
bit_depth = png_get_bit_depth(png_ptr, info_ptr);
color_type = png_get_color_type(png_ptr, info_ptr); // read png data
png_size_t rowbytes;
png_bytep* row_pointers = (png_bytep*)malloc( sizeof(png_bytep) * _img_height ); rowbytes = png_get_rowbytes(png_ptr, info_ptr); size_t _datalen = rowbytes * _img_height;
unsigned char* _data = static_cast<unsigned char*>(malloc(_datalen * sizeof(unsigned char)));
if (!_data)
{
if (row_pointers != nullptr)
{
free(row_pointers);
}
break;
} for (unsigned short i = 0; i < _img_height; ++i)
{
row_pointers[i] = _data + i*rowbytes;
}
png_read_image(png_ptr, row_pointers); png_read_end(png_ptr, nullptr); ret = true;
} while (0); if (png_ptr)
{
png_destroy_read_struct(&png_ptr, (info_ptr) ? &info_ptr : 0, 0);
} return ret;
} // 第一种方法:获取图片数据,这种方法,可以获取到图片真正的数据,还可以通过fwrite生成新的图片
// cocos2dx使用的是这个方法,但是我不太懂为什么我这边搞错了
bool getImageData(const char* path) {
// 根据路径获取图片数据
bool ret = false;
size_t size = 0;
size_t readsize; unsigned char* buffer = nullptr;
do
{
FILE* file = fopen(path, "rb");
if(file == NULL) {
std::cout << "Failed to open Image." << std::endl;
return NULL;
} fseek(file,0,SEEK_END);
size = ftell(file);
fseek(file,0,SEEK_SET); buffer = (unsigned char*)malloc(sizeof(unsigned char) * size); readsize = fread(buffer, sizeof(unsigned char), size, file);
fclose(file);
} while (0); if (nullptr == buffer || 0 == readsize)
{
printf("Get data from file %s failed", path);
}
else
{
_sp_image_data.fastSet(buffer, readsize);
} // 对图片数据进行初始化
unsigned char* unpackedData = nullptr;
ssize_t unpackedLen = 0; unpackedData = const_cast<unsigned char*>(_sp_image_data.getBytes());
unpackedLen = _sp_image_data.getSize();
ret = initWithImageData(unpackedData, unpackedLen); return ret;
} // 第二种方法:获取图片数据,这个方法非常简单,但是只获得了rgb数据,并不能根据这个数据去生成新的图片
// 因为不是学习的重点,所以暂时先使用这个方法
bool getImageData2(const char* path) {
// 根据路径获取图片数据
bool ret = true;
int width, height;
unsigned char* image_data = SOIL_load_image(path, &width, &height, 0, SOIL_LOAD_RGB);
const ssize_t size = strlen((const char*)image_data);
_sp_image_data.fastSet(image_data, size);
_sp_image_size.fastSet(width, height); SOIL_free_image_data(image_data); return ret;
} void initSpriteData(const char* path) {
bool ret = getImageData2(path);
if (!ret) {
cout << "get iamge data is failed." << endl;
return ;
}
else {
cout << "get iamge data is success." << endl; //测试图片数据
FILE * file;
file = fopen("/Users/staff/Desktop/abc.png","wb");
if (file)
{
fwrite(_sp_image_data.getBytes(),1,_sp_image_data.getSize(), file);
}
fclose(file); } glEnable(GL_TEXTURE_2D);
OPGL::activeTexture(GL_TEXTURE0); //绑定
glGenTextures(1, &_sp_textureID);
glBindTexture(GL_TEXTURE_2D, _sp_textureID); //纹理过滤函数,纹理图像空间映射到帧缓冲图像空间
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); //线性过滤函数
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); //生成2d纹理
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, _sp_image_size.getX(), _sp_image_size.getY(), 0, GL_RGB, GL_UNSIGNED_BYTE, _sp_image_data.getBytes());
glGenerateMipmap(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, 0);
} void setSpritePosition(float x, float y) {
_sp_position.x = x;
_sp_position.y = y; if (_sp_position.x == x && _sp_position.y == y)
return; _sp_position.x = x;
_sp_position.y = y; _sp_transformUpdated = true;
} // 将精灵的顶点数据填充到绘制的数组中
void filledVertexData() {
// 分配顶点属性数据
memcpy(Vertexs + _filledVertex, _sp_triangles.verts, sizeof(V3F_C4B_T2F) * _sp_triangles.vertCount); // 更新每一个顶点的模型矩阵,根据这个去设置顶点着色器的值
for (ssize_t i = 0; i < _sp_triangles.vertCount; ++i) {
V3F_C4B_T2F *v_i = &Vertexs[i + _filledVertex];
Vector3 *v_p = (Vector3 *)&v_i->vertices;
_sp_modelView.transformPoint(v_p);
} // 获取索引信息
const unsigned int* indices = _sp_triangles.indices;
for (ssize_t i = 0; i < _sp_triangles.indexCount; ++i) {
Indices[i + _filledIndex] = _filledVertex + indices[i];
} // 已处理的顶点下标
_filledVertex += _sp_triangles.vertCount;
_filledIndex += _sp_triangles.indexCount;
} void drawDrawCommand() {
if (_sp_triangles.indexCount % 3 != 0) {
ssize_t count = _sp_triangles.indexCount;
_sp_triangles.indexCount = count / 3 * 3;
} int indexToDraw = 0; //Upload buffer to VBO
if(_filledVertex <= 0 || _filledIndex <= 0)
{
cout << "image data is null" << endl;
return;
}
// 设置默认的顶点对象数组
OPGL::bindVAO(_triangleVAO); glBindBuffer(GL_ARRAY_BUFFER, _triangleVBO[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(Vertexs[0]) * _filledVertex, nullptr, GL_DYNAMIC_DRAW);
void *buf = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
memcpy(buf, Vertexs, sizeof(Vertexs[0])* _filledVertex);
// 映射缓存
glUnmapBuffer(GL_ARRAY_BUFFER);
glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _triangleVBO[1]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(Indices[0]) * _filledIndex, Indices, GL_STATIC_DRAW); OPGL::bindVAO(0); indexToDraw += _sp_triangles.indexCount; if (indexToDraw > 0) {
glUseProgram(_program); glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
OPGL::activeTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, _sp_textureID); // 绑定,即可从_textureID中取出图像数据
glUniform1i(_uniforms[UNIFORM_SAMPLER0], 0); OPGL::bindVAO(_triangleVAO);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
cout << "drawing..." << endl;
OPGL::bindVAO(0);
} // 恢复默认的顶点对象数组
_filledVertex = 0;
_filledIndex = 0;
} void setSpriteVertexAttribInfo() {
memset(&_sp_quad, 0, sizeof(_sp_quad)); _sp_quad.bl.colors = Color4B::BLUE;
_sp_quad.br.colors = Color4B::WHITE;
_sp_quad.tl.colors = Color4B::BLACK;
_sp_quad.tr.colors = Color4B::RED; // 1.指的是要处理纹理的部分
float left = 0.0f;
float right = 1.0f;
float top = 1.0f;
float bottom = 0.0f; // 左下角
_sp_quad.bl.texCoords.u = left;
_sp_quad.bl.texCoords.v = bottom; // 右下角
_sp_quad.br.texCoords.u = bottom;
_sp_quad.br.texCoords.v = right; // 左上角
_sp_quad.tl.texCoords.u = top;
_sp_quad.tl.texCoords.v = left; // 右上角
_sp_quad.tr.texCoords.u = top;
_sp_quad.tr.texCoords.v = right; // 2.处理四边形的顶点坐标
float x1 = -0.5f;
float y1 = -0.5f;
float x2 = 0.5f;
float y2 = 0.5f; // 左下角
_sp_quad.bl.vertices.set(x1, y1, 0.0f);
// 右下角
_sp_quad.br.vertices.set(x2, y1, 0.0f);
// 左上角
_sp_quad.tl.vertices.set(x1, y2, 0.0f);
// 右上角
_sp_quad.tr.vertices.set(x2, y2, 0.0f); // 3.更新到三角形上
_sp_triangles.vertCount = 4; //顶点个数
_sp_triangles.verts = (V3F_C4B_T2F*)&_sp_quad; //顶点数据
_sp_triangles.indexCount = 6; //索引个数
_sp_triangles.indices = quadIndices;
} //设置VAO
void setVAOAndVBO() { _sp_triangles.outVerts();
_sp_triangles.outIndics(); glGenVertexArrays(1, &_triangleVAO);
// 绑定VAO
OPGL::bindVAO(_triangleVAO);
// 创建生成两个VBO
glGenBuffers(2, &_triangleVBO[0]);
// 顶点Buffer
glBindBuffer(GL_ARRAY_BUFFER, _triangleVBO[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(V3F_C4B_T2F) * _sp_triangles.vertCount, _sp_triangles.verts, GL_STATIC_DRAW); GLuint _positionSlot = glGetAttribLocation(_program, ATTRIBUTE_NAME_POSITION);
GLuint _colorSlot = glGetAttribLocation(_program, ATTRIBUTE_NAME_COLOR);
GLuint _textureCoordsSlot = glGetAttribLocation(_program, ATTRIBUTE_NAME_TEXCOOD); // vertices
// 位置
glEnableVertexAttribArray(_positionSlot);
glVertexAttribPointer(_positionSlot, 3, GL_FLOAT, GL_FALSE, sizeof(V3F_C4B_T2F), (GLvoid*) offsetof( V3F_C4B_T2F, vertices)); // colors
// 颜色
glEnableVertexAttribArray(_colorSlot);
glVertexAttribPointer(_colorSlot, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(V3F_C4B_T2F), (GLvoid*) offsetof( V3F_C4B_T2F, colors)); // tex coords
// 纹理坐标数据
glEnableVertexAttribArray(_textureCoordsSlot);
glVertexAttribPointer(_textureCoordsSlot, 2, GL_FLOAT, GL_FALSE, sizeof(V3F_C4B_T2F), (GLvoid*) offsetof( V3F_C4B_T2F, texCoords)); // 索引Buffer
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _triangleVBO[1]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned int) * _sp_triangles.indexCount, _sp_triangles.indices, GL_STATIC_DRAW); OPGL::bindVAO(0); glBindVertexArray(0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
} void init() {
// 只有源
reset();
glViewport(0, 0, 800, 600); glBlendFunc(GL_ONE, GL_ZERO);
glEnable(GL_TEXTURE_2D);
glDisable(GL_DEPTH_TEST); //2d没用
// Enable texturing
// glEnable(GL_CULL_FACE); //启用剔除功能
glEnable(GL_BLEND); //启用混合方式
glDisable(GL_DITHER); //启用抖动功能
glDepthMask(GL_FALSE); //将深度缓冲区设置成只读形式
glDepthFunc(GL_LESS); //指定深度缓冲比较函数,如果输入的深度值小于参考值,则通过
glDepthRange(0.0f, 1.0f); //用于决定窗口坐标的z值
glClearDepth(1.0f); //用指定值来清除指定的深度缓冲区值
glCullFace (GL_BACK); //表示剔除多边形的哪种面
glFrontFace(GL_CCW); //设置点序列逆时针方向围成的多边形为正面
glClearStencil(0);//用指定值来清除指定的模版缓冲区值
glStencilMask( 0xFFFFFFFF ); //指定模版的掩码
glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
} int main(int argc, const char * argv[]) {
GLFWwindow* window;
/* Initialize the library */
if (!glfwInit())
return -1; /* Create a windowed mode window and its OpenGL context */
window = glfwCreateWindow(800, 600, "First OpenGL", NULL, NULL);
if (!window)
{
glfwTerminate();
return -1;
} /* Make the window's context current */
glfwMakeContextCurrent(window);
glewExperimental = GL_TRUE;
glewInit();
glfwSwapInterval(1); // 开启功能
init();
// 创建program和shader
initProgramShader(CCPositionTextureColorVert, CCPositionTextureColorFrag);
// 对texture进行绘制
initSpriteData("/Users/staff/Desktop/fgh/fgh/wall.jpg");
// 设置精灵的顶点属性数据
setSpriteVertexAttribInfo();
// 设置顶点数组缓冲区
setVAOAndVBO(); /* Loop until the user closes the window */
while (!glfwWindowShouldClose(window))
{
glfwPollEvents(); int width, height;
glfwGetFramebufferSize(window, &width, &height);
glViewport(0, 0, width, height);
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT); // 填充数据
filledVertexData();
// 根据的到的数据进行绘制
drawDrawCommand(); glfwSwapBuffers(window);
} glfwTerminate();
glDeleteVertexArrays(1, &_triangleVAO);
glDeleteBuffers(1, &_triangleVBO[0]);
glDeleteBuffers(1, &_triangleVBO[1]); return 0;
}

这里面有个很坑的地方,也是因为自己的基础不扎实,导致找了一天的bug。sizeof()我直接用一个对象指针作为参数,以为是个对象数组应该可以,但是应该是不行的,应该将其类型作为参数,并且乘以对象个数才能得到数组的大小。

还有一个注意的地方,因为只是作为测试使用,所以没有进行封装,只有一个triangleCommand,也就是只会绘制一个指令,后续同样以这个工程作为测试工程。

先是顶点shader:

const char* CCPositionTextureColorVert = STRINGIFY(
attribute vec4 a_position;
attribute vec4 a_color;
attribute vec2 a_texCoord; varying vec4 ourColor;
varying vec2 TexCoord; void main() {
gl_Position = a_position;
ourColor = a_color;
TexCoord = a_texCoord;
}
);

接下来的是片元shader

const char* CCPositionTextureColorFrag = STRINGIFY(
varying vec4 ourColor;
varying vec2 TexCoord; //varying vec4 color; //uniform float mixValue; void main() {
//gl_FragColor = mix(texture2D(CC_Texture0, TexCoord) * vec4(ourColor, 1.0), texture2D(CC_Texture1, vec2(-TexCoord.x, TexCoord.y)), mixValue);
gl_FragColor = ourColor * texture2D(CC_Texture0, TexCoord);
}
);

拆分Cocos2dx渲染部分代码的更多相关文章

  1. 拆分Cocos2dx 渲染项目 总结

    因为只拆分了渲染的内容,所以代码只针对渲染部分进行分析. 代码涉及到这些类: CCImage,对图片的数据进行操作 CCNode,CCSprite,结点类 CCProgram,CCRenderer,C ...

  2. 将Cocos2dX渲染到MFC窗口上

    引用:http://www.cnblogs.com/windeer/archive/2012/11/18/2767750.html 引言 现在智能手机已经慢慢进入大众化,移动类应用开始火爆起来,游戏类 ...

  3. cocos2d-x JS 纯代码渲染Lable描边

    /** * Enables shadow style and sets color, offset and blur radius styles. * @param {cc.Color} shadow ...

  4. cocos2d-x渲染流程

    Cocos2Dx之渲染流程 发表于8个月前(2014-08-08 22:46)   阅读(3762) | 评论(2) 17人收藏此文章, 我要收藏 赞2 如何快速提高你的薪资?-实力拍“跳槽吧兄弟”梦 ...

  5. cocos2dx渲染架构

    2dx的时代UI树便利和渲染是没有分开的,遍历UI树的时候就渲染.3dx版本为了分离了ui树的遍历和渲染,先遍历生成渲染命令发到渲染队列,之后遍历渲染命令队列开始渲染.这样做的好处是渲染命令可以重用, ...

  6. cocos2D-X从的源代码的分析cocos2D-X学习OpenGL(1)----cocos2D-X渲染架构

     个人原创.欢迎转载,转载请注明原文地址http://blog.csdn.net/bill_man 从本篇文章開始,将分析cocos2D-X 3.0源码,第一部分是从cocos2D-X学习OpenGL ...

  7. Cocos2d-x调用Java 代码

    Java代码: package com.dishu; import com.dishu.org.R; import android.app.Activity; import android.app.A ...

  8. 解决vue变量未渲染前代码显示问题

    在网络加载缓慢或者刷新的时候总会有那么一瞬间出现vue的模板代码,实在很影响美观,对于我这种有强迫症的人来说实在是忍无可忍,后来经过查找资料,终于发现了解决方法,可以使用vue现成的指令来解决这个问题 ...

  9. KoaHub平台基于Node.js开发的Koa EJS渲染插件代码信息详情

    koa-ejs ejs render middleware for koa koa-ejs Koa ejs view render middleware. support all feature of ...

随机推荐

  1. [Android Studio] Android Studio如何快速生成get,set,tostring,构造函数

    刚开始使用Android Studio时,在创建一个javabean时,很习惯的在JavaBean类中,右键去找生成get,set等选项.但是很遗憾,找不到. 那这边如何快速的set,get或者生成构 ...

  2. 002_安装第三方APP好的站点及解除安全与隐私限制

    一.解除安全与隐私限制的任何来源. http://bbs.feng.com/read-htm-tid-10714286.html 接下来,我们就打开终端,然后输入以下命令:   sudo spctl ...

  3. 26 About the go command go命令行

    About the go command  go命令行 Motivation Configuration versus convention Go's conventions Getting star ...

  4. MongoDB的安装与使用

    MongoDB是一款NoSql数据库.NoSql数据库叫非关系型数据库,NoSql的全名Not only sql.是为了解决高并发.高可用.高可扩展,以及大数据存储等一系列问题而产生的数据库解决方案. ...

  5. Jmeter 接口测试-请求 Headers 与传参方式

    1.添加信息表头. 注意:1.使用Parameters时,Content-Type要么不传,要么传application/x-www-form-urlencoded,因为不传时默认值就是applica ...

  6. java基础71 XML解析中的【DOM和SAX解析工具】相关知识点(网页知识)

    本文知识点(目录):本文下面的“实例及附录”全是DOM解析的相关内容 1.xml解析的含义    2.XML的解析方式    3.xml的解析工具    4.XML的解析原理    5.实例    6 ...

  7. tomcat运行内存溢出问题

    tomcat 运行内存配置优化 /opt/apache-tomcat-7.0.65/bin/catalina.sh:JAVA_OPTS="$JAVA_OPTS -Dfile.encoding ...

  8. 洛谷P1525关押罪犯

    传送门啦 想让最大值最小,所以,这题可以用二分法,排序之后发现可以并查集,因为要使最大值最小,排序后这个最大值是存在的. 对于会冲突的两个罪犯,我们连一条无向边,然后按权值从大到小排序,从大到小枚举每 ...

  9. C++之构造函数的继承

    #include<iostream> usingnamespace std; classBase1 { public: Base1()=default; Base1(const strin ...

  10. IDEA创建Spring Boot项目

    首先安装Spring Boot CLI 先确定自己安装的JDK是1.8版本或者以上,然后下载Srping Boot CLI,Spring Boot CLI下载地址,下载下来是一个压缩包,解压,得到一个 ...