I have tried to update the code to Cocos2d version 2.0 using a shader with position/color (no texture). The code is pasted below ... It will not render and I am very very sure it is because I am still not getting OpenGL ES 2.0 in Cocos2d. Can anyone help me to understand why it does not work?
==========================================================================
// Water.h
#import <Foundation/Foundation.h>
#import "cocos2d.h"
@interface Water : CCNode
{
CGRect _bounds;
int _count;
float _diffusion;
float _damping;
float _offset;
float *_h1;
float *_h2;
}
// 'bounds' are the rectangle to draw for the water. The top of the 'bounds' is the rest height for the water, it will wave above and below it
// 'count' is the number of slices to simulate. One per 10-20 px is usually sufficient
// 'damping' is how fast the water settels back to rest. 1.0 is never (bad), 0.0 is immidiately (also bad). 0.99 is a decent dampening amount
// 'diffusion' is how fast the waves distribute to neighbours. Values outside of 0.6 - 0.9 can become unstable
+ (id) waterWithBounds:(CGRect)bounds count:(int)count damping:(float)damping diffusion:(float)diffusion;
// Will create a splash at the given x location within the water bounds
- (void) makeSplashAt:(float)x;
@end
==========================================================================
// Water.m
#import "Water.h"
static CCGLProgram *shader_ = nil;
static int colorLocation_ = -1;
static int pointSizeLocation_ = -1;
static ccColor4F color_ = { 0.0f, 0.0f, 1.0f, 0.3f };
@implementation Water
+ (id) waterWithBounds:(CGRect)bounds count:(int)count damping:(float)damping diffusion:(float)diffusion
{
return [[self alloc] initWithBounds:bounds count:count damping:damping diffusion:diffusion];
}
- (id) initWithBounds:(CGRect)bounds count:(int)count damping:(float)damping diffusion:(float)diffusion
{
if ((self = [super init]))
{
// Store variables
_bounds = bounds;
_count = count;
_damping = damping;
_diffusion = diffusion;
_h1 = calloc(_count, sizeof(float));
_h2 = calloc(_count, sizeof(float));
// Set content size
// self.contentSize = CGSizeMake(bounds.size.width - bounds.origin.x, bounds.size.height - bounds.origin.y);
// Attach shaders - use build in shaders for now
self.shaderProgram = [[CCGLProgram alloc] initWithVertexShaderByteArray:ccPosition_uColor_vert fragmentShaderByteArray:ccPosition_uColor_frag];
[self.shaderProgram addAttribute:kCCAttributeNamePosition index:kCCVertexAttrib_Position];
[self.shaderProgram addAttribute:kCCAttributeNameColor index:kCCVertexAttrib_Color];
[self.shaderProgram link];
[self.shaderProgram updateUniforms];
/* shader_ = [[CCShaderCache sharedShaderCache] programForKey:kCCShader_Position_uColor];
colorLocation_ = glGetUniformLocation(shader_->program_, "u_color");
pointSizeLocation_ = glGetUniformLocation(shader_->program_, "u_pointSize"); */
CCLOG(@"Water created at %@", NSStringFromCGRect(bounds));
}
return self;
}
- (void) dealloc
{
free(_h1);
free(_h2);
}
- (void) makeSplashAt:(float)x
{
int index = MAX(0, MIN((int)(x / [self dx]), _count - 1));
_h2[index] += CCRANDOM_MINUS1_1() * 20.0f;
}
- (void) draw
{
[self verlet];
[self diffuse];
GLfloat dx = [self dx];
GLfloat top = _bounds.size.height;
// Build a vertex array and render it
struct Vertex { GLfloat x, y; };
struct Vertex verts[_count * 2];
for (int i = 0; i < _count; i++)
{
GLfloat x = i * dx;
verts[2 * i + 0] = (struct Vertex) { x, 0 };
verts[2 * i + 1] = (struct Vertex) { x, (top + _h2[i]) };
}
const GLfloat triColor[] =
{
0.0f, 0.0f, 1.0f, 1.0f,
0.0f, 0.0f, 1.0f, 1.0f,
0.0f, 0.0f, 1.0f, 1.0f,
};
ccGLBlendFunc( CC_BLEND_SRC, CC_BLEND_DST );
ccGLUseProgram(shaderProgram_ ->program_);
CHECK_GL_ERROR_DEBUG();
ccGLEnableVertexAttribs(kCCVertexAttrib_Position | kCCVertexAttrib_Color);
CHECK_GL_ERROR_DEBUG();
glVertexAttribPointer(kCCVertexAttrib_Position, 2, GL_FLOAT, GL_FALSE, 0, verts);
glVertexAttribPointer(kCCVertexAttrib_Color, 4, GL_FLOAT, GL_FALSE, 0, triColor);
CHECK_GL_ERROR_DEBUG();
glDrawArrays(GL_TRIANGLE_STRIP, 0, (GLsizei) _count * 2);
CHECK_GL_ERROR_DEBUG();
/* [shader_ use];
[shader_ setUniformForModelViewProjectionMatrix];
[shader_ setUniformLocation:colorLocation_ with4fv:(GLfloat *) &color_.r count:1];
ccGLEnableVertexAttribs( kCCVertexAttrib_Position );
glVertexAttribPointer(kCCVertexAttrib_Position, 2, GL_FLOAT, GL_FALSE, 0, verts);
glDrawArrays(GL_TRIANGLE_STRIP, 0, (GLsizei) _count * 2);
CC_INCREMENT_GL_DRAWS(1); */
}
- (void) verlet
{
for (int i = 0; i < _count; i++)
{
_h1[i] = 2.0 * _h2[i] - _h1[i];
}
float *temp = _h2;
_h2 = _h1;
_h1 = temp;
}
static inline float diffuse(float diff, float damp, float prev, float curr, float next)
{
return (curr * diff + ((prev + next) * 0.5f) * (1.0f - diff)) * damp;
}
- (void) diffuse
{
float prev = _h2[0];
float curr = _h2[0];
float next = _h2[0];
_h2[0] = diffuse(_diffusion, _damping, prev, curr, next);
for (int i = 1; i < (_count - 1); ++i)
{
prev = curr;
curr = next;
next = _h2[i + 1];
_h2[i] = diffuse(_diffusion, _damping, prev, curr, next);
}
prev = curr;
curr = next;
_h2[_count - 1] = diffuse(_diffusion, _damping, prev, curr, next);
}
- (float)dx
{
return _bounds.size.width / (GLfloat)(_count - 1);
}
@end