这是一个非常酷的教程,但我不知道如何在cocos2d-x 3中做到这一点。我已经翻译了下面的代码
- (id)init
{
self = [super init];
if (self) {
// 1
sprite = [CCSprite spriteWithFile:@"Default.png"];
sprite.anchorPoint = CGPointZero;
sprite.rotation = 90;
sprite.position = ccp(0, 320);
[self addChild:sprite];
// 2
const GLchar * fragmentSource = (GLchar*) [[NSString stringWithContentsOfFile:[CCFileUtils fullPathFromRelativePath:@"CSEColorRamp.fsh"] encoding:NSUTF8StringEncoding error:nil] UTF8String];
sprite.shaderProgram = [[CCGLProgram alloc] initWithVertexShaderByteArray:ccPositionTextureA8Color_vert
fragmentShaderByteArray:fragmentSource];
[sprite.shaderProgram addAttribute:kCCAttributeNamePosition index:kCCVertexAttrib_Position];
[sprite.shaderProgram addAttribute:kCCAttributeNameTexCoord index:kCCVertexAttrib_TexCoords];
[sprite.shaderProgram link];
[sprite.shaderProgram updateUniforms];
// 3
colorRampUniformLocation = glGetUniformLocation(sprite.shaderProgram->program_, "u_colorRampTexture");
glUniform1i(colorRampUniformLocation, 1);
// 4
colorRampTexture = [[CCTextureCache sharedTextureCache] addImage:@"colorRamp.png"];
[colorRampTexture setAliasTexParameters];
// 5
[sprite.shaderProgram use];
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, [colorRampTexture name]);
glActiveTexture(GL_TEXTURE0);
}
return self;
}
并获得了这个:
Vec2 origin = Director::getInstance()->getVisibleOrigin();
sprite = Sprite::create("HelloWorld.png");
sprite->setAnchorPoint(Vec2(0, 0));
sprite->setRotation(3);
sprite->setPosition(origin);
addChild(sprite);
const GLchar * fragmentSource = FileUtils::getInstance()->getStringFromFile("CSEColorRamp.fsh").c_str();
GLProgram* p = GLProgram::createWithByteArrays(ccPositionTextureA8Color_vert, fragmentSource);
sprite->setGLProgram(p);
p->bindAttribLocation(GLProgram::ATTRIBUTE_NAME_POSITION, GLProgram::VERTEX_ATTRIB_POSITION);
p->bindAttribLocation(GLProgram::ATTRIBUTE_NAME_TEX_COORD, GLProgram::VERTEX_ATTRIB_TEX_COORD);
p->link();
p->updateUniforms();
// 3
colorRampUniformLocation = glGetUniformLocation(sprite->getGLProgram()->getProgram(), "u_colorRampTexture");
glUniform1i(colorRampUniformLocation, 1);
// 4
colorRampTexture = Director::getInstance()->getTextureCache()->addImage("colorRamp.png");
colorRampTexture->setAliasTexParameters();
// 5
sprite->getGLProgram()->use();
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, colorRampTexture->getName());
glActiveTexture(GL_TEXTURE0);
但它不起作用。它显示一个带有2个绘制调用的黑屏。怎么了?我是否将所有制服和属性正常传递给片段着色器。我是否正确初始化了程序?
答案 0 :(得分:1)
以下是如何在cocos2d-x 3.1中使用着色器的示例:
.h文件
#ifndef __HELLOWORLD_SCENE_H__
#define __HELLOWORLD_SCENE_H__
#include "cocos2d.h"
using namespace cocos2d;
class HelloWorld : public cocos2d::Layer
{
public:
// there's no 'id' in cpp, so we recommend returning the class instance pointer
static cocos2d::Scene* createScene();
// Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone
virtual bool init();
virtual void visit(Renderer *renderer, const Mat4 &transform, bool transformUpdated) override;
//we call our actual opengl commands here
void onDraw();
// implement the "static create()" method manually
CREATE_FUNC(HelloWorld);
private:
CustomCommand _customCommand;
GLuint vao;
GLuint vertexVBO;
GLuint colorVBO;
};
#endif // __HELLOWORLD_SCENE_H__
.cpp文件
#include "HelloWorldScene.h"
USING_NS_CC;
Scene* HelloWorld::createScene()
{
// 'scene' is an autorelease object
auto scene = Scene::create();
// 'layer' is an autorelease object
auto layer = HelloWorld::create();
// add layer as a child to scene
scene->addChild(layer);
// return the scene
return scene;
}
// on "init" you need to initialize your instance
bool HelloWorld::init()
{
//////////////////////////////
// 1. super init first
if ( !Layer::init() )
{
return false;
}
//create my own program
auto program = new GLProgram;
program->initWithFilenames("myVertextShader.vert", "myFragmentShader.frag");
program->link();
//set uniform locations
program->updateUniforms();
// this->setGLProgram(GLProgramCache::getInstance()->getGLProgram(GLProgram::SHADER_NAME_POSITION_COLOR));
this->setGLProgram(program);
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
typedef struct {
float Position[2];
float Color[4];
} Vertex;
// auto size = Director::getInstance()->getVisibleSize();
Vertex data[] =
{
{{-1,-1},{0,1,0,1}},
{{1,-1},{1,0,0,1}},
{ {-1,1},{0,0,1,1}},
{{1,1},{0,1,0,1}}
};
GLubyte indices[] = { 0,1,2, //第一个三角形索引
2,3,1}; //第二个三角形索引
glGenBuffers(1, &vertexVBO);
glBindBuffer(GL_ARRAY_BUFFER, vertexVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
GLuint positionLocation = glGetAttribLocation(program->getProgram(), "a_position");
// CCLOG("position =%d", positionLocation);
glEnableVertexAttribArray(positionLocation);
glVertexAttribPointer(positionLocation,
2,
GL_FLOAT,
GL_FALSE,
sizeof(Vertex),
(GLvoid*)offsetof(Vertex,Position));
//set for color
// glGenBuffers(1, &colorVBO);
// glBindBuffer(GL_ARRAY_BUFFER, colorVBO);
// glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
GLuint colorLocation = glGetAttribLocation(program->getProgram(), "a_color");
glEnableVertexAttribArray(colorLocation);
glVertexAttribPointer(colorLocation,
4,
GL_FLOAT,
GL_FALSE,
sizeof(Vertex),
(GLvoid*)offsetof(Vertex,Color));
GLuint indexVBO;
glGenBuffers(1, &indexVBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexVBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices) , indices, GL_STATIC_DRAW);
program->autorelease();
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
// 使用vao http://blog.sina.com.cn/s/blog_4a657c5a01016f8s.html
return true;
}
void HelloWorld::visit(cocos2d::Renderer *renderer, const Mat4 &transform, bool transformUpdated)
{
Layer::draw(renderer, transform, transformUpdated);
//send custom command to tell the renderer to call opengl commands
_customCommand.init(_globalZOrder);
_customCommand.func = CC_CALLBACK_0(HelloWorld::onDraw, this);
renderer->addCommand(&_customCommand);
}
void HelloWorld::onDraw()
{
//question1: why the triangle goes to the up side
//如果使用对等矩阵,则三角形绘制会在最前面
Director::getInstance()->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
Director::getInstance()->loadIdentityMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
Director::getInstance()->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);
Director::getInstance()->loadIdentityMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);
auto glProgram = getGLProgram();
glProgram->use();
//set uniform values, the order of the line is very important
glProgram->setUniformsForBuiltins();
auto size = Director::getInstance()->getWinSize();
//use vao
glBindVertexArray(vao);
GLuint uColorLocation = glGetUniformLocation(glProgram->getProgram(), "u_color");
float uColor[] = {1.0, 0.0, 0.0, 1.0};
glUniform4fv(uColorLocation,1, uColor);
// glDrawArrays(GL_TRIANGLES, 0, 6);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE,(GLvoid*)0);
glBindVertexArray(0);
CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1, 6);
CHECK_GL_ERROR_DEBUG();
Director::getInstance()->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);
Director::getInstance()->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
}
myVertextShader.vert顶点着色器
attribute vec4 a_position;
attribute vec4 a_color;
varying vec4 v_fragmentColor;
uniform vec4 u_color;
void main()
{
gl_Position = CC_MVPMatrix * a_position;
v_fragmentColor = a_color * u_color;
}
myFragmentShader.frag片段着色器
varying vec4 v_fragmentColor;
void main()
{
gl_FragColor = v_fragmentColor;
}