拆分Cocos2dx渲染部分代码
纹理实现
思想
这个是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渲染部分代码的更多相关文章
- 拆分Cocos2dx 渲染项目 总结
因为只拆分了渲染的内容,所以代码只针对渲染部分进行分析. 代码涉及到这些类: CCImage,对图片的数据进行操作 CCNode,CCSprite,结点类 CCProgram,CCRenderer,C ...
- 将Cocos2dX渲染到MFC窗口上
引用:http://www.cnblogs.com/windeer/archive/2012/11/18/2767750.html 引言 现在智能手机已经慢慢进入大众化,移动类应用开始火爆起来,游戏类 ...
- cocos2d-x JS 纯代码渲染Lable描边
/** * Enables shadow style and sets color, offset and blur radius styles. * @param {cc.Color} shadow ...
- cocos2d-x渲染流程
Cocos2Dx之渲染流程 发表于8个月前(2014-08-08 22:46) 阅读(3762) | 评论(2) 17人收藏此文章, 我要收藏 赞2 如何快速提高你的薪资?-实力拍“跳槽吧兄弟”梦 ...
- cocos2dx渲染架构
2dx的时代UI树便利和渲染是没有分开的,遍历UI树的时候就渲染.3dx版本为了分离了ui树的遍历和渲染,先遍历生成渲染命令发到渲染队列,之后遍历渲染命令队列开始渲染.这样做的好处是渲染命令可以重用, ...
- cocos2D-X从的源代码的分析cocos2D-X学习OpenGL(1)----cocos2D-X渲染架构
个人原创.欢迎转载,转载请注明原文地址http://blog.csdn.net/bill_man 从本篇文章開始,将分析cocos2D-X 3.0源码,第一部分是从cocos2D-X学习OpenGL ...
- Cocos2d-x调用Java 代码
Java代码: package com.dishu; import com.dishu.org.R; import android.app.Activity; import android.app.A ...
- 解决vue变量未渲染前代码显示问题
在网络加载缓慢或者刷新的时候总会有那么一瞬间出现vue的模板代码,实在很影响美观,对于我这种有强迫症的人来说实在是忍无可忍,后来经过查找资料,终于发现了解决方法,可以使用vue现成的指令来解决这个问题 ...
- KoaHub平台基于Node.js开发的Koa EJS渲染插件代码信息详情
koa-ejs ejs render middleware for koa koa-ejs Koa ejs view render middleware. support all feature of ...
随机推荐
- xss的一个tip
其实可能不能算tip吧. 分享一下吧. unicode有四种编码方式 源文本:The &#x [Hex]:The &# [Decimal]:The \U [Hex]:\U0054\U0 ...
- MVVM模式的 数据绑定
数据绑定要达到的效果 数据绑定要达到什么效果呢,就是在界面中绑定了数据源之后,数据在界面上的修改能反映到绑定源,同时绑定源的修改也能反映到界面上.从界面反映到绑定的数据源是很容易理解的,因为在绑定过程 ...
- ASP.net-空白页的问题
protected void Application_Error(object sender, EventArgs e) { ILog log = LogMan ...
- java基础34 泛型的使用
本文知识点(目录): 1.泛型的好处 2.泛型在集合中的常见应用(这里只用String类型举例) 3.在泛型中是不能使用基本数据类型,如果需要使用基本数据类型,那么就使用基本数据类型对应的 ...
- 读书笔记--C陷阱与缺陷(三)
第三章 1. 指针与数组 书中强调C中数组注意的两点: 1) C语言只有一维数组,但是数组元素可以是任何类型对象,是另外一个数组时就产生了二维数组.数组大小是常数(但GCC实现了变长数组..) ...
- MySQL学习笔记:repeat、loop循环
一.repeat循环 # ---- repeat ---- DELIMITER $$ CREATE PROCEDURE test_repeat() BEGIN ; REPEAT ; UNTIL a E ...
- 搜索入门之dfs--经典的迷宫问题解析
今天来谈一下dfs的入门,以前看到的dfs入门,那真的是入门吗,都是把dfs的实现步骤往那一贴,看完是知道dfs的步骤了,但是对于代码实现还是没有概念.今天准备写点自己的心得,真的是字面意思--入门. ...
- hdu 3951 硬币围成一圈(博弈)
n个硬币围成一个环 每次只能取1-K个硬币 最后取完者胜 假如5个硬币 每次取1-2个情况1 先手取1个 后手取剩下4个中间2个 破坏了连续 虽然最后剩2个,但先手只能取一个 然后后再取一个 后手胜 ...
- Mongodb配置:error:10061 由于目标计算机积极拒绝,无法连接
相信很多学Node的同学,在进入MongoDB后台管理 Shell的时候都会“遇到error:10061 由于目标计算机积极拒绝,无法连接”这种情况,很多情况都是dbpath与dblog的路径没有配置 ...
- Solr的入门知识
一.Solr的简介 Solr 是Apache下的一个顶级开源项目,采用Java开发,它是基于Lucene的全文搜索服务.Solr可以独立运行在Jetty.Tomcat等这些Servlet容器中.都 ...