258 lines
6.8 KiB
C
258 lines
6.8 KiB
C
/* Copyright (c) 2007 Scott Lembcke
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
* in the Software without restriction, including without limitation the rights
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
* copies of the Software, and to permit persons to whom the Software is
|
|
* furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in
|
|
* all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
* SOFTWARE.
|
|
*/
|
|
|
|
#include <string.h>
|
|
|
|
#include "GL/glew.h"
|
|
#include "GL/glfw.h"
|
|
|
|
#include "chipmunk_private.h"
|
|
#include "ChipmunkDemo.h"
|
|
#include "ChipmunkDemoShaderSupport.h"
|
|
#include "ChipmunkDemoTextSupport.h"
|
|
|
|
#include "VeraMoBd.ttf_sdf.h"
|
|
|
|
//#define Scale 3.0f
|
|
#define Scale 0.70f
|
|
#define LineHeight (18.0f*Scale)
|
|
|
|
static GLuint program;
|
|
static GLuint texture;
|
|
|
|
struct v2f {GLfloat x, y;};
|
|
typedef struct Vertex {struct v2f vertex, tex_coord; Color color;} Vertex;
|
|
typedef struct Triangle {Vertex a, b, c;} Triangle;
|
|
|
|
static GLuint vao = 0;
|
|
static GLuint vbo = 0;
|
|
|
|
// char -> glyph indexes generated by the lonesock tool.
|
|
static int glyph_indexes[256];
|
|
|
|
void
|
|
ChipmunkDemoTextInit(void)
|
|
{
|
|
GLint vshader = CompileShader(GL_VERTEX_SHADER, GLSL(
|
|
attribute vec2 vertex;
|
|
attribute vec2 tex_coord;
|
|
attribute vec4 color;
|
|
|
|
varying vec2 v_tex_coord;
|
|
varying vec4 v_color;
|
|
|
|
void main(void){
|
|
// TODO get rid of the GL 2.x matrix bit eventually?
|
|
gl_Position = gl_ModelViewProjectionMatrix*vec4(vertex, 0.0, 1.0);
|
|
|
|
v_color = color;
|
|
v_tex_coord = tex_coord;
|
|
}
|
|
));
|
|
|
|
GLint fshader = CompileShader(GL_FRAGMENT_SHADER, GLSL(
|
|
uniform sampler2D u_texture;
|
|
|
|
varying vec2 v_tex_coord;
|
|
varying vec4 v_color;
|
|
|
|
float aa_step(float t1, float t2, float f)
|
|
{
|
|
//return step(t2, f);
|
|
return smoothstep(t1, t2, f);
|
|
}
|
|
|
|
void main(void)
|
|
{
|
|
float sdf = texture2D(u_texture, v_tex_coord).a;
|
|
|
|
//float fw = fwidth(sdf)*0.5;
|
|
float fw = length(vec2(dFdx(sdf), dFdy(sdf)))*0.5;
|
|
|
|
float alpha = aa_step(0.5 - fw, 0.5 + fw, sdf);
|
|
gl_FragColor = v_color*(v_color.a*alpha);
|
|
// gl_FragColor = vec4(1, 0, 0, 1);
|
|
}
|
|
));
|
|
|
|
program = LinkProgram(vshader, fshader);
|
|
CHECK_GL_ERRORS();
|
|
|
|
// GLint index = -1;//glGetUniformLocation(program, "u_texture");
|
|
// glUniform1i(index, 0);
|
|
// CHECK_GL_ERRORS();
|
|
|
|
// Setu VBO and VAO.
|
|
#if __APPLE__
|
|
glGenVertexArraysAPPLE(1, &vao);
|
|
glBindVertexArrayAPPLE(vao);
|
|
#else
|
|
glGenVertexArrays(1, &vao);
|
|
glBindVertexArray(vao);
|
|
#endif
|
|
|
|
glGenBuffers(1, &vbo);
|
|
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
|
|
|
SET_ATTRIBUTE(program, struct Vertex, vertex, GL_FLOAT);
|
|
SET_ATTRIBUTE(program, struct Vertex, tex_coord, GL_FLOAT);
|
|
SET_ATTRIBUTE(program, struct Vertex, color, GL_FLOAT);
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
|
#if __APPLE__
|
|
glBindVertexArrayAPPLE(0);
|
|
#else
|
|
glBindVertexArray(0);
|
|
#endif
|
|
CHECK_GL_ERRORS();
|
|
|
|
// Load the SDF font texture.
|
|
glGenTextures(1, &texture);
|
|
glBindTexture(GL_TEXTURE_2D, texture);
|
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, sdf_tex_width, sdf_tex_height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, sdf_data);
|
|
glGenerateMipmap(GL_TEXTURE_2D);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
|
|
CHECK_GL_ERRORS();
|
|
|
|
// Fill in the glyph index array.
|
|
for(int i=0; i<sdf_num_chars; i++){
|
|
int char_index = sdf_spacing[i*8];
|
|
glyph_indexes[char_index] = i;
|
|
}
|
|
}
|
|
|
|
#undef MAX
|
|
#define MAX(__a__, __b__) (__a__ > __b__ ? __a__ : __b__)
|
|
|
|
static size_t triangle_capacity = 0;
|
|
static size_t triangle_count = 0;
|
|
static Triangle *triangle_buffer = NULL;
|
|
|
|
static Triangle *PushTriangles(size_t count)
|
|
{
|
|
if(triangle_count + count > triangle_capacity){
|
|
triangle_capacity += MAX(triangle_capacity, count);
|
|
triangle_buffer = (Triangle *)realloc(triangle_buffer, triangle_capacity*sizeof(Triangle));
|
|
}
|
|
|
|
Triangle *buffer = triangle_buffer + triangle_count;
|
|
triangle_count += count;
|
|
return buffer;
|
|
}
|
|
|
|
static GLfloat
|
|
PushChar(int character, GLfloat x, GLfloat y, Color color)
|
|
{
|
|
int i = glyph_indexes[character];
|
|
GLfloat w = (GLfloat)sdf_tex_width;
|
|
GLfloat h = (GLfloat)sdf_tex_height;
|
|
|
|
GLfloat gw = (GLfloat)sdf_spacing[i*8 + 3];
|
|
GLfloat gh = (GLfloat)sdf_spacing[i*8 + 4];
|
|
|
|
GLfloat txmin = sdf_spacing[i*8 + 1]/w;
|
|
GLfloat tymin = sdf_spacing[i*8 + 2]/h;
|
|
GLfloat txmax = txmin + gw/w;
|
|
GLfloat tymax = tymin + gh/h;
|
|
|
|
GLfloat s = Scale/scale_factor;
|
|
GLfloat xmin = x + sdf_spacing[i*8 + 5]/scale_factor*Scale;
|
|
GLfloat ymin = y + (sdf_spacing[i*8 + 6]/scale_factor - gh)*Scale;
|
|
GLfloat xmax = xmin + gw*Scale;
|
|
GLfloat ymax = ymin + gh*Scale;
|
|
|
|
Vertex a = {{xmin, ymin}, {txmin, tymax}, color};
|
|
Vertex b = {{xmin, ymax}, {txmin, tymin}, color};
|
|
Vertex c = {{xmax, ymax}, {txmax, tymin}, color};
|
|
Vertex d = {{xmax, ymin}, {txmax, tymax}, color};
|
|
|
|
Triangle *triangles = PushTriangles(2);
|
|
Triangle t0 = {a, b, c}; triangles[0] = t0;
|
|
Triangle t1 = {a, c, d}; triangles[1] = t1;
|
|
|
|
return sdf_spacing[i*8 + 7]*s;
|
|
}
|
|
|
|
#undef ChipmunkDemoTextDrawString
|
|
|
|
void
|
|
ChipmunkDemoTextDrawString(cpVect pos, char *str)
|
|
{
|
|
Color c = LAColor(1.0f, 1.0f);
|
|
GLfloat x = (GLfloat)pos.x, y = (GLfloat)pos.y;
|
|
|
|
for(int i=0, len=strlen(str); i<len; i++){
|
|
if(str[i] == '\n'){
|
|
y -= LineHeight;
|
|
x = (GLfloat)pos.x;
|
|
// } else if(str[i] == '*'){ // print out the last demo key
|
|
// glutBitmapCharacter(GLUT_BITMAP_HELVETICA_10, 'A' + demoCount - 1);
|
|
} else {
|
|
x += (GLfloat)PushChar(str[i], x, y, c);
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
ChipmunkDemoTextFlushRenderer(void)
|
|
{
|
|
// triangle_count = 0;
|
|
// ChipmunkDemoTextDrawString(cpv(-300, 0), "0.:,'");
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
|
glBufferData(GL_ARRAY_BUFFER, sizeof(Triangle)*triangle_count, triangle_buffer, GL_STREAM_DRAW);
|
|
|
|
glUseProgram(program);
|
|
|
|
#if __APPLE__
|
|
glBindVertexArrayAPPLE(vao);
|
|
#else
|
|
glBindVertexArray(vao);
|
|
#endif
|
|
glDrawArrays(GL_TRIANGLES, 0, triangle_count*3);
|
|
|
|
CHECK_GL_ERRORS();
|
|
}
|
|
|
|
void
|
|
ChipmunkDemoTextClearRenderer(void)
|
|
{
|
|
triangle_count = 0;
|
|
}
|
|
|
|
static int pushed_triangle_count = 0;
|
|
void
|
|
ChipmunkDemoTextPushRenderer(void)
|
|
{
|
|
pushed_triangle_count = triangle_count;
|
|
}
|
|
|
|
void
|
|
ChipmunkDemoTextPopRenderer(void)
|
|
{
|
|
triangle_count = pushed_triangle_count;
|
|
}
|
|
|
|
|