Repeating OpenGL-es texture bound to hills in cocos2d 3.2 - c++

ORIGINAL ARTICLE
I am in the process of trying to implement raywenderlich's tutorial on generating hills with repeating striped coordinates using cocos2d, This article was written for Cocos2D, and as I am trying to port it to Cocos2Dx 3.2 This means updating it for openGl-es 2. So far everything has worked perfectly, However I am having problems with getting the texture of the hill to repeat properly and also after some repeatation the texture start degrade ...
please help me to get texture properly.......
Here is my code:
#define Point_FROM_B2VEC(v) Point((v.x*PTM_RATIO),(v.y*PTM_RATIO))
#define B2VEC_FROM_Point(v) b2Vec2(v.x/PTM_RATIO,v.y/PTM_RATIO)
#define PTM_RATIO 32
#define MAX_HILL_POINTS 15
#define MAX_SEGMENTS MAX_HILL_POINTS*10
#define MAX_COORDINATES 600
Point hillTopVertices[MAX_COORDINATES],hillBottomVertices[MAX_COORDINATES];
Point hillTopTexCoords[MAX_COORDINATES];
Point hillBottomTexCoords[MAX_COORDINATES];
GLuint terraintopTexId, terrainBottomTexId;
float terrainTopTexSize, terrainBottomTexSize;
Sending the hills the texture:
texture = Director::getInstance()->getTextureCache()->addImage("surface.png");
terraintopTexId = texture->getName();
terrainTopTexSize = texture->getPixelsWide()/2;
//terrain top texture
texture1 = Director::getInstance()->getTextureCache()->addImage("old_stone_wall_textures_v3_3000x2000_1.jpg");
terrainBottomTexId = texture1->getName();
terrainBottomTexSize = texture1->getPixelsWide()/2;
void Terrain::generateCoordinates()
{
int nTopVertCount = 0;
int nTopVertCount1 = 0;
//get the hill vertex and texcoordinates
for(short i = 0; i < MAX_SEGMENTS; ++i)
{
Point point1 = Point_FROM_B2VEC(vertices[i]);
Point point2 = Point_FROM_B2VEC(vertices[i+1]);
CCLOG("%f",terrainBottomTexSize);
hillTopVertices[nTopVertCount1] = Point(point1.x, point1.y+16);
hillTopTexCoords[nTopVertCount1++] = Point(point1.x/terrainTopTexSize, 1);
hillTopVertices[nTopVertCount1] = Point(point2.x, point2.y+16);
hillTopTexCoords[nTopVertCount1++] = Point(point2.x/terrainTopTexSize, 1);
hillTopVertices[nTopVertCount1] = Point(point1.x, point1.y-16);
hillTopTexCoords[nTopVertCount1++] = Point(point1.x/terrainTopTexSize, 0);
hillTopVertices[nTopVertCount1] = Point(point2.x, point2.y-16);
hillTopTexCoords[nTopVertCount1++] = Point(point2.x/terrainTopTexSize, 0);
}
for(short i = 0; i < MAX_SEGMENTS; ++i)
{
Point point1 = Point_FROM_B2VEC(vertices[i]);
Point point2 = Point_FROM_B2VEC(vertices[i+1]);
hillBottomVertices[nTopVertCount] = Point(point1.x, point1.y-terrainBottomTexSize+1);
hillBottomTexCoords[nTopVertCount++] = Point(point1.x/terrainBottomTexSize, 1);
hillBottomVertices[nTopVertCount] = Point(point2.x, point2.y-terrainBottomTexSize+1);
hillBottomTexCoords[nTopVertCount++] = Point(point2.x/terrainBottomTexSize, 1);
hillBottomVertices[nTopVertCount] = Point(point1.x, point1.y+2);
hillBottomTexCoords[nTopVertCount++] = Point(point1.x/terrainBottomTexSize, 0);
hillBottomVertices[nTopVertCount] = Point(point2.x, point2.y+2);
hillBottomTexCoords[nTopVertCount++] = Point(point2.x/terrainBottomTexSize, 0);
}
//energy adding
//CCLOG("hillsegment---%d,pointx---%f,pointy---%f,offset--%f",i,point1.x,point1.y,offsetX);
}
void Terrain::draw(Renderer *renderer, const Mat4 &transform, uint32_t flags)
{
Node::draw(renderer, transform, flags);
_renderCmds[0].init(0.0f);
_renderCmds[0].func = CC_CALLBACK_0(Terrain::onDraw, this, transform);
renderer->addCommand(&_renderCmds[0]);
}
void Terrain::onDraw(const Mat4 &transform) {
auto glProgram = getGLProgram();
glProgram->use();
glProgram->setUniformsForBuiltins(transform);
GL::bindTexture2D( terrainBottomTexId );
GL::enableVertexAttribs( GL::VERTEX_ATTRIB_FLAG_POS_COLOR_TEX );
glBindBuffer(GL_ARRAY_BUFFER, 0);
glEnableVertexAttribArray(GLProgram::VERTEX_ATTRIB_POSITION);
glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 2, GL_FLOAT, GL_FALSE, 0, hillBottomVertices);
glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_TEX_COORD, 2, GL_FLOAT, GL_FALSE, 0, hillBottomTexCoords);
glDrawArrays(GL_TRIANGLE_STRIP, 0, (GLsizei)MAX_COORDINATES);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
GL::bindTexture2D(terraintopTexId );
GL::enableVertexAttribs( GL::VERTEX_ATTRIB_FLAG_POS_COLOR_TEX );
glBindBuffer(GL_ARRAY_BUFFER, 0);
glEnableVertexAttribArray(GLProgram::VERTEX_ATTRIB_POSITION);
glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 2, GL_FLOAT, GL_FALSE, 0, hillTopVertices);
glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_TEX_COORD, 2, GL_FLOAT, GL_FALSE, 0, hillTopTexCoords);
glDrawArrays(GL_TRIANGLE_STRIP, 0, (GLsizei)MAX_COORDINATES);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
}

Related

Compute shader can't get result image

I am using the compute shader to get a column of colors to match the conditions and I want to get the results for further processing. I want to get the output data in image1D imgOutput, but get_img can't get anything, did I do something wrong?
the texture in the first block has been generated before.
Shader spriteRowProgram, spriteColumnProgram;
unsigned int resultTexture = 0;
const std::string path = found::utils::Environment::GetRunPath();
const std::string sprite_row_path = path + "shaders/glfw_sprite_row.comp";
spriteRowProgram = Shader(sprite_row_path);
std::vector<GLfloat> get_img(qMax(TEX_WIDTH, TEX_HEIGHT) * 4);
glGenTextures(1, &resultTexture);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_1D, resultTexture);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA32F, qMax(TEX_WIDTH, TEX_HEIGHT), 0, GL_RGBA, GL_FLOAT, get_img.data());
glActiveTexture(GL_TEXTURE0 + 1);
glBindTexture(GL_TEXTURE_2D, texture);
spriteRowProgram.use();
glUniform1i(1, 1);
glBindImageTexture(1, texture, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32F);
glUniform1i(0, 0);
glBindImageTexture(0, resultTexture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
glClear(GL_COLOR_BUFFER_BIT);
spriteRowProgram.setInt("input_width", TEX_WIDTH);
spriteRowProgram.setInt("input_height", TEX_HEIGHT);
glDispatchCompute(TEX_WIDTH, 1, 1);
glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
#version 430 core
layout (local_size_x = 1, local_size_y = 1) in;
layout(rgba32f, location = 0, binding = 0) uniform writeonly image1D imgOutput;
// texture samplers
layout(rgba32f, location = 1, binding = 1) uniform readonly image2D inputImage;
uniform int input_width;
uniform int input_height;
void main()
{
vec4 baseColor = imageLoad(inputImage, ivec2(0, 0));
bool alpha = baseColor.w == 1;
bool success = true;
for (int i = 0; i <= input_height; ++i)
{
vec4 current = imageLoad(inputImage, ivec2(gl_GlobalInvocationID.x, i));
if (alpha) {
if (current.w > 0.99) continue;
else {
success = false;
break;
}
} else {
vec4 difference = baseColor - current;
success = abs(difference.x) < 0.01 && abs(difference.y) < 0.01 && abs(difference.z) < 0.01;
if (success) continue;
else {
break;
}
}
}
if (success) baseColor = ivec4(0.1, 0.1, 0.1, 0.1);
else baseColor = ivec4(1.0, 1.0, 1.0, 1.0);
imageStore(imgOutput, int(gl_GlobalInvocationID.x), baseColor);
}
One issue might be that if you want to access images after the compute shader, the argument for glMemoryBarrier should be GL_SHADER_IMAGE_ACCESS_BARRIER_BIT and not GL_SHADER_STORAGE_BARRIER_BIT.
So
spriteRowProgram.setInt("input_width", TEX_WIDTH);
spriteRowProgram.setInt("input_height", TEX_HEIGHT);
glDispatchCompute(TEX_WIDTH, 1, 1);
glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
should really be
spriteRowProgram.setInt("input_width", TEX_WIDTH);
spriteRowProgram.setInt("input_height", TEX_HEIGHT);
glDispatchCompute(TEX_WIDTH, 1, 1);
glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);

FreeType library is not display with tutorial code

-Using Mac Retina display 2304x1440
I succeeded in including the FreeType library and tried to draw based on the tutorial but nothing was displayed.
There are no errors, so I can not identify the problem.
// For LoadShaders
#include "shader.hpp"
#include <vector>
#include <cstring>
#include <GL/glew.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
using namespace glm;
#include <ft2build.h>
#include FT_FREETYPE_H
FT_Library library;
FT_Face face;
GLuint TextShaderID;
GLuint uniform_tex;
GLuint uniform_color;
GLuint vbo00;
// I have already acquired this font.
const char * fontfilename = "OpenSans-Regular.ttf";
void iii()
{
/* Initialize the FreeType2 library */
if (FT_Init_FreeType(&library)) {
fprintf(stderr, "Could not init freetype library\n");
}
/* Load a font */
if (FT_New_Face(library, fontfilename, 0, &face)) {
fprintf(stderr, "Could not open font %s\n", fontfilename);
}
// Initialize Shader (Here is not problem. Maybe.)
TextShaderID = LoadShaders( "material/shader/FreeType.vertexshader", "material/shader/FreeType.fragmentshader" );
// Initialize uniforms' IDs
uniform_tex = glGetUniformLocation( TextShaderID, "myTextureSampler" );
uniform_color = glGetUniformLocation( TextShaderID, "texcol" );
glGenBuffers(1, &vbo00);
}
void render_text(const char *text, float x, float y, float sx, float sy) {
const char *p;
FT_GlyphSlot g = face->glyph;
glActiveTexture(GL_TEXTURE0);
GLuint tex;
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_2D, tex);
glUniform1i(uniform_tex, 0);
/* We require 1 byte alignment when uploading texture data */
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
/* Clamping to edges is important to prevent artifacts when scaling */
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
/* Linear filtering usually looks best for text */
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
/* Set up the VBO for our vertex data */
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vbo00);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0);
/* Loop through all characters */
for (p = text; *p; p++) {
/* Try to load and render the character */
if (FT_Load_Char(face, *p, FT_LOAD_RENDER))
continue;
/* Upload the "bitmap", which contains an 8-bit grayscale image, as an alpha texture */
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, g->bitmap.width, g->bitmap.rows, 0, GL_ALPHA, GL_UNSIGNED_BYTE, g->bitmap.buffer);
/* Calculate the vertex and texture coordinates */
float x2 = x + g->bitmap_left * sx;
float y2 = -y - g->bitmap_top * sy;
float w = g->bitmap.width * sx;
float h = g->bitmap.rows * sy;
GLfloat box[4][4] = {
{x2, -y2, 0, 0},
{x2 + w, -y2, 1, 0},
{x2, -y2 - h, 0, 1},
{x2 + w, -y2 - h, 1, 1},
};
/* Draw the character on the screen */
glBufferData(GL_ARRAY_BUFFER, sizeof box, box, GL_DYNAMIC_DRAW);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
/* Advance the cursor to the start of the next character */
x += (g->advance.x >> 6) * sx;
y += (g->advance.y >> 6) * sy;
}
glDisableVertexAttribArray(0);
glDeleteTextures(1, &tex);
}
void rrr()
{
glUseProgram(TextShaderID);
/* White background */
glClearColor(1, 1, 1, 1);
glClear(GL_COLOR_BUFFER_BIT);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
float sx = 2/2304/4;
float sy = 2/1440/4;
FT_Set_Pixel_Sizes(face, 0, 48);
/* Effects of alignment */
GLfloat red[4] = { 1, 0, 0, 1 };
glUniform4fv(uniform_color, 1, red);
render_text("The Quick Brown Fox Jumps Over The Lazy Dog", 0, 0, sx, sy);
glutSwapBuffers();
}
float sx = 2/2304/4;
float sy = 2/1440/4;
are integral divisions. If an integral number is divided by a greater integral number, than the result is 0.
You've to do floating point divisions:
float sx = 2.0f/2304.0f/4.0f;
float sy = 2.0f/1440.0f/4.0f;
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA,
g->bitmap.width, g->bitmap.rows, 0,
GL_ALPHA, GL_UNSIGNED_BYTE, g->bitmap.buffer);
generates a texture, where the data is encoded to the alpha channel. This has to be considered in the shader code, when the texture is looked up (by .a):
e.g.
#version 460
// [...]
uniform sampler2D myTextureSampler;
uniform vec4 texcol;
void main()
{
vec4 col = texcol * texture(myTextureSampler, uv).a;
// [...]
}
Anyway GL_ALPHA is deprecated and Legacy OpenGL. This means this won't work if you use a core profile Context.
Use GL_RED instead:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RED,
g->bitmap.width, g->bitmap.rows, 0,
GL_RED, GL_UNSIGNED_BYTE, g->bitmap.buffer);
Read the data from the red color channel (.r) in the fragment shader:
#version 460 core
// [...]
uniform sampler2D myTextureSampler;
uniform vec4 texcol;
void main()
{
vec4 col = texcol * texture(myTextureSampler, uv).r;
// [...]
}

OpenGL Texture corruption

i am rendering simple pixel buffer in OpenGL. First, i create a quad, then i create a texture. It works correctly if there is no changes in buffer. When i change my buffer and add new buffer into texture by glTexSubImage2D or glTexImage2D my texture's top section corrupts like image.
I create my buffer like this.
int length = console->width * console->height * 3;
GLubyte buf[length];
for(int i = 0; i < length; i += 3) {
buf[i] = 0;
buf[i + 1] = 0;
buf[i + 2] = 0;
}
console->buffer = buf;
I create texture like this.
glGenTextures(1, &console->textureID);
glBindTexture(GL_TEXTURE_2D, console->textureID);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, console->width, console->height, 0, GL_RGB, GL_UNSIGNED_BYTE, console->buffer);
tpUseShader(console); // -> calls glUseShader(console->programID);
glUniform1i(glGetUniformLocation(console->programID, "texture"), 0);
I update texture like this.
glBindTexture(GL_TEXTURE_2D, console->textureID);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, console->width, console->height, GL_RGB, GL_UNSIGNED_BYTE, console->buffer);
For testing i change my buffer like this in render function
if(console->buffer[6] == 255) {
console->buffer[6] = 0; // 6 is second pixel's red value.
console->buffer[10] = 255; // 10 is third pixel's green value
} else {
console->buffer[6] = 255;
console->buffer[10] = 0;
}
Then i call tpUseShader and render my quad.
How can i fix this problem?
I changed my console size to 10x10 and run again this time i got same results but, in image you can see from bottom left 3rd pixel is dark blue. When i print printf("3rd pixel: %d- %d - %d\n", console->buffer[12], console->buffer[13], console->buffer[14]);. value i got red: 0 green: 0 blue: 0 values. That means my buffer is normal.
I got the solution. As pleluron said in comments of question. I changed buf in to console->buffer, and it worked!. Now my buffer initialization code is like this:
console->buffer = malloc(sizeof(GLubyte) * length);
for(int i = 0; i < length; i += 3) {
console->buffer[i] = 0;
console->buffer[i + 1] = 0;
console->buffer[i + 2] = 0;
}

Open gl draw turns white after one frame drawn

I am newbie in Opengl. I used the following example from Qt as a start in Opengl as I know Qt.
http://doc.qt.io/qt-5/qtquick-scenegraph-openglunderqml-squircle-cpp.html
I replaced the paint function of the program with following code with an intent to draw chess board pattern. Following is not the paint or render function of my program
paint()
{
if (!m_program) {
initializeOpenGLFunctions();
m_program = new QOpenGLShaderProgram();
m_program->addShaderFromSourceCode(QOpenGLShader::Vertex,
"attribute highp vec4 vertices;"
"varying highp vec2 coords;"
"void main() {"
" gl_Position = vertices;"
" coords = vertices.xy;"
"}");
m_program->addShaderFromSourceCode(QOpenGLShader::Fragment,
"uniform lowp float t;"
"varying highp vec2 coords;"
"void main() {"
" lowp float i = 1. - (pow(abs(coords.x), 4.) + pow(abs(coords.y), 4.));"
" i = smoothstep(t - 0.8, t + 0.8, i);"
" i = floor(i * 20.) / 20.;"
" gl_FragColor = vec4(coords * .5 + .5, i, i);"
"}");
m_program->bindAttributeLocation("vertices", 0);
m_program->link();
}
auto width = static_cast<float>(m_viewportSize.width());
auto height = static_cast<float>(m_viewportSize.height());
auto a = 2.f / width;
auto b = 2.f / height;
std::vector<float> matrix =
{
a , 0, 0, 0,
0, -b, 0, 0,
0, 0, 1, 0,
-1, 1, 0, 1
};
// Set the projection matrix
glMatrixMode(GL_PROJECTION);
glLoadMatrixf(matrix.data());
// Initialize vertices:
std::vector<float> vertices =
{
0, 0,
0, height,
width, height,
width, 0
};
// Initialize colors
std::vector<float> colors =
{
1, 0, 0,
0, 1, 0,
0, 0, 1,
0, 1, 1
};
// Initialize texture virtice
std::vector<float> texCoord =
{
0, 0,
0, 1,
1, 1,
1, 0
};
// Create texture: simple chess board 8x8
auto numRows = 8u;
auto numCols = 8u;
auto character = 172u;
auto remain = 255u - character;
std::vector<unsigned char> texture(numCols * numRows);
for (auto i = 0u; i < texture.size(); ++i)
texture[i] = ((i + (i / numCols)) % 2) * remain + character;
// Upload to GPU texture
unsigned textureID;
glGenTextures(1, &textureID);
glBindTexture(GL_TEXTURE_2D, textureID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, numCols, numRows, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, texture.data());
// Initialize clear colors
glClearColor(0.f, 0.f, 0.f, 1.f);
// Activate necessary states
glEnable(GL_TEXTURE_2D);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glVertexPointer(2, GL_FLOAT, 0, vertices.data());
glColorPointer(3, GL_FLOAT, 0, colors.data());
glTexCoordPointer(2, GL_FLOAT, 0, texCoord.data());
// render
glClear(GL_COLOR_BUFFER_BIT);
glDrawArrays(GL_QUADS, 0, 4);
m_program->disableAttributeArray(0);
m_program->release();
m_window->resetOpenGLState();
}
The chess board is drawn. But its drawn for a split second & then the screen turns fully white. I want to draw the chess board pattern continiously with each frame draw.
Can someone pls point out what might be going wrong ?
At the very top you have:
if (!m_program) {
then you initialize m_program, at the very bottom you have:
m_program->release();
which as Harish in comments points out is equivalent to calling glUseProgram(0);. So in the next iteration of paint your shader is not bound and not available.
According to docs, the reverse of release(); is bind(); so (I am not expert on this class) the solution might be to call QOpenGLShaderProgram::bind() on the next iteration of your paint.
For future reference, it's a good idea to run opengl programs through a graphics debugger like gDEbugger to give you an insight into what's actually happening inside the API.

Fill in a polygon with texture/color using CCRenderTexture

I have a concave polygon. The first thing I do is to triangulate it and store all triangle points in a vertex array.
I am trying to fill that polygon with texture or color but none of the two solutions work.
Here is the code when trying to get a texture with one color:
CCTexture2D* TextureTest::textureColorWithVertices(CCPoint* vertices,
int count,
CCRect spriteRect)
{
CCRenderTexture *renderTexture = CCRenderTexture::create(spriteRect.size.width, spriteRect.size.height);
renderTexture->beginWithClear(1, 1, 1, 0);
mShaderProgram->use();
mShaderProgram->setUniformForModelViewProjectionMatrix();
ccVertex2F* verts = new ccVertex2F[count];
for( int i=0;i<count;i++) {
verts[i].x = vertices[i].x + spriteRect.size.width / 2;//*CC_CONTENT_SCALE_FACTOR();
verts[i].y = vertices[i].y + spriteRect.size.height / 2;//*CC_CONTENT_SCALE_FACTOR();
}
ccColor4F* colors = new ccColor4F[count];
ccColor4F red = ccc4f(1, 0, 0, 1);
for (int i = 0; i < count; i++)
{
colors[i] = red;
}
glDisable(GL_TEXTURE_2D);
mShaderProgram->setUniformLocationWith4f(mColorLocation, 1.0f, 1.0f, 1.0f, 1.0f);
glVertexAttribPointer(kCCVertexAttrib_Position, 2, GL_FLOAT, GL_FALSE, 0, verts);
glVertexAttribPointer(kCCVertexAttrib_Color, 4, GL_FLOAT, GL_FALSE, 0, colors);
glDrawArrays(GL_TRIANGLES, 0, count);
glEnable(GL_TEXTURE_2D);
CC_INCREMENT_GL_DRAWS(1);
delete[] colors;
delete[] verts;
renderTexture->end();
return renderTexture->getSprite()->getTexture();
}
And the other one with a 256*256 seamless texture:
CCTexture2D* TextureTest::textureWithVertices(CCPoint* vertices,
int count,
CCTexture2D* baseTexture,
CCRect spriteRect)
{
CCRenderTexture *renderTexture = CCRenderTexture::create(spriteRect.size.width, spriteRect.size.height);
renderTexture->beginWithClear(1, 1, 1, 0);
mShaderProgram->use();
mShaderProgram->setUniformForModelViewProjectionMatrix();
ccVertex2F* verts = new ccVertex2F[count];
for( int i=0;i<count;i++)
{
verts[i].x = vertices[i].x + spriteRect.size.width / 2;//*CC_CONTENT_SCALE_FACTOR();
verts[i].y = vertices[i].y + spriteRect.size.height / 2;//*CC_CONTENT_SCALE_FACTOR();
}
ccTex2F* uvs = new ccTex2F[count];
float baseTexturePixelsWide = baseTexture->getPixelsWide();
float baseTexturePixelsHigh = baseTexture->getPixelsHigh();
for( int i=0;i<count;i++)
{
uvs[i].u = ((spriteRect.size.width / 2 + vertices[i].x) / baseTexturePixelsWide) * CC_CONTENT_SCALE_FACTOR();
uvs[i].v = ((spriteRect.size.height / 2 - vertices[i].y) / baseTexturePixelsHigh) * CC_CONTENT_SCALE_FACTOR();
}
ccGLBindTexture2D( baseTexture->getName() );
mShaderProgram->setUniformLocationWith4f(mColorLocation, 1.0f, 1.0f, 1.0f, 1.0f);
glVertexAttribPointer(kCCVertexAttrib_TexCoords, 2, GL_FLOAT, GL_FALSE, 0, uvs);
glVertexAttribPointer(kCCVertexAttrib_Position, 2, GL_FLOAT, GL_FALSE, 0, verts);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glDrawArrays(GL_TRIANGLES, 0, count);
CC_INCREMENT_GL_DRAWS(1);
delete[] uvs;
delete[] verts;
renderTexture->end();
return renderTexture->getSprite()->getTexture();
}
Finally I call these functions in this piece of code, rockPolygon is the original sprite:
//Get the seamless square texture
CCSpriteBatchNode* rockBatch = CCSpriteBatchNode::create("rock_small.png", kDefaultSpriteBatchCapacity);
//Triangulate the old sprite
vector<CCPoint> triangles = triangulateSprite(rockPolygon);
//CCTexture2D* rockTexture = textureColorWithVertices(&triangles[0], triangles.size(), rockPolygon->getOriginalRect());
CCTexture2D* rockTexture = textureWithVertices(&triangles[0], triangles.size(), rockBatch->getTexture(), rockPolygon->getOriginalRect());
CCSprite* genSprite = new CCSprite();
genSprite->initWithTexture(rockTexture);
genSprite->setPosition(ccp(200,200));
addChild(genSprite); //add generated sprite to main layer
I checked the triangulation, it works fine. I also remove all code between renderTexture->beginWithClear(1, 1, 1, 0); and renderTexture->end(), set the alpha channel to 1 beginWithClear(1, 1, 1, 1) and a white square is correctly displaying. So I guess the problem comes from the opengl calls but I can't find what is wrong. Do you have any idea on how to solve this issue please?
You're already on cocos2d 2.x. Your triangulation to convex shapes works. Then you can draw the shapes with CCDrawNode, no need to write your own render code.