Created
April 9, 2017 23:49
-
-
Save anonymous/c4837a02838302201ba0dc1f14689423 to your computer and use it in GitHub Desktop.
SDL render touch input on Android
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <cstdlib> | |
#include <iostream> | |
#include <stdexcept> | |
#include <cmath> | |
#include <SDL2/SDL.h> | |
#ifdef ENV_ANDROID_SDL | |
#include <SDL2/SDL_main.h> | |
#include <GLES2/gl2.h> | |
#include <GLES2/gl2ext.h> | |
#else | |
#include <SDL2/SDL_opengl.h> | |
#include <glad/glad.h> | |
#endif | |
#ifdef ENV_ANDROID_SDL | |
std::string const k_shader_version_str = "#version 100\n"; | |
#else | |
std::string const k_shader_version_str = "#version 120\n"; | |
#endif | |
std::string const k_vsh_source = | |
k_shader_version_str+ | |
"\n" | |
"// attributes\n" | |
"attribute vec4 a_v4_position;\n" | |
"\n" | |
"void main()\n" | |
"{\n" | |
" gl_Position = a_v4_position;\n" | |
"}\n"; | |
std::string const k_fsh_source = | |
k_shader_version_str+ | |
"\n" | |
"// varyings\n" | |
"\n" | |
"void main()\n" | |
"{\n" | |
" gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n" | |
"}\n"; | |
struct ApplicationData | |
{ | |
SDL_Window* window{nullptr}; | |
SDL_GLContext gl_context; | |
GLuint prog_id{0}; | |
GLuint vbo_id{0}; | |
GLint attrib_loc_position{0}; | |
#ifdef ENV_ANDROID_SDL | |
unsigned int win_width{768}; | |
unsigned int win_height{1134}; | |
#else | |
unsigned int win_width{384}; | |
unsigned int win_height{567}; | |
#endif | |
float input_x{0.0f}; | |
float input_y{0.0f}; | |
float input_s{120.0f}; | |
float rads{0.0f}; | |
float disp_x{0.0f}; | |
float disp_y{0.0f}; | |
}; | |
void InitSDL(SDL_Window* &window, SDL_GLContext& context, | |
unsigned int win_width, unsigned int win_height) | |
{ | |
// init sdl | |
SDL_Init(SDL_INIT_VIDEO); | |
// set requested opengl context params | |
#ifdef ENV_ANDROID_SDL | |
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION,2); | |
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION,0); | |
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK,SDL_GL_CONTEXT_PROFILE_ES); | |
#else | |
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION,2); | |
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION,1); | |
#endif | |
// create a window | |
window = SDL_CreateWindow( | |
"OpenGL",0,0, | |
win_width, | |
win_height, | |
SDL_WINDOW_OPENGL|SDL_WINDOW_RESIZABLE); | |
if(!window) { | |
std::string const err = | |
"Failed to create window "+ | |
std::string(SDL_GetError()); | |
SDL_Quit(); | |
throw std::runtime_error(err); | |
} | |
// get the opengl context | |
context = SDL_GL_CreateContext(window); | |
if(!context) { | |
std::string const err = | |
"Error: Failed to create context"+ | |
std::string(SDL_GetError()); | |
SDL_Quit(); | |
throw std::runtime_error(err); | |
} | |
// load opengl functions (must be done after | |
// getting a valid context) | |
#ifndef ENV_ANDROID_SDL | |
if(!gladLoadGL()) { | |
std::string const err = | |
"Error: Error loading OpenGL functions"; | |
SDL_GL_DeleteContext(context); | |
SDL_Quit(); | |
throw std::runtime_error(err); | |
} | |
#endif | |
#ifdef ENV_ANDROID_SDL | |
if(SDL_GL_SetSwapInterval(1) < 0) { | |
std::string const err = | |
"Error: Failed to set vsync: " + | |
std::string(SDL_GetError()); | |
SDL_GL_DeleteContext(context); | |
SDL_Quit(); | |
throw std::runtime_error(err); | |
} | |
if(SDL_SetHint(SDL_HINT_ANDROID_SEPARATE_MOUSE_AND_TOUCH,"1") < 0) { | |
throw std::runtime_error("Failed to set mouse/touch hint"); | |
} | |
#endif | |
} | |
void InitGL(GLuint& prog_id, | |
GLuint& vbo_id, | |
GLint& attrib_loc_position) | |
{ | |
(void)vbo_id; | |
std::cout << "OpenGL version: " << glGetString(GL_VERSION) << std::endl; | |
// vertex shader | |
auto vsh_id = glCreateShader(GL_VERTEX_SHADER); | |
char const * vsh_source = k_vsh_source.c_str(); | |
glShaderSource(vsh_id,1,&vsh_source,nullptr); | |
glCompileShader(vsh_id); | |
GLint vsh_ok = GL_FALSE; | |
glGetShaderiv(vsh_id,GL_COMPILE_STATUS,&vsh_ok); | |
if(vsh_ok==GL_FALSE) { | |
throw std::runtime_error("Failed to compiler vertext shader"); | |
} | |
// fragment shader | |
auto fsh_id = glCreateShader(GL_FRAGMENT_SHADER); | |
char const * fsh_source = k_fsh_source.c_str(); | |
glShaderSource(fsh_id,1,&fsh_source,nullptr); | |
glCompileShader(fsh_id); | |
GLint fsh_ok = GL_FALSE; | |
glGetShaderiv(fsh_id,GL_COMPILE_STATUS,&fsh_ok); | |
if(fsh_ok==GL_FALSE) { | |
throw std::runtime_error("Error: Failed to compile fragment shader"); | |
} | |
// create shader program | |
prog_id = glCreateProgram(); | |
glAttachShader(prog_id,vsh_id); | |
glAttachShader(prog_id,fsh_id); | |
glLinkProgram(prog_id); | |
GLint link_ok = GL_FALSE; | |
glGetProgramiv(prog_id,GL_LINK_STATUS,&link_ok); | |
if(link_ok==GL_FALSE) { | |
glDeleteProgram(prog_id); | |
throw std::runtime_error("Error: Failed to link shader"); | |
} | |
// get attribute locations | |
attrib_loc_position = glGetAttribLocation(prog_id,"a_v4_position"); | |
// set gl clear color | |
glClearColor(0,0,0,1); | |
} | |
float ToNDCX(float x, float win_width) | |
{ | |
x /= win_width; | |
x = x*2.0f - 1.0f; | |
return x; | |
} | |
float ToNDCY(float y, float win_height) | |
{ | |
y /= win_height; | |
y = (1.0f-y)*2.0f - 1.0f; | |
return y; | |
} | |
void Render(ApplicationData& app_data) | |
{ | |
auto& vbo_id = app_data.vbo_id; | |
auto& input_x = app_data.input_x; | |
auto& input_y = app_data.input_y; | |
auto& input_s = app_data.input_s; | |
auto& rads = app_data.rads; | |
auto& win_width = app_data.win_width; | |
auto& win_height = app_data.win_height; | |
auto& disp_x = app_data.disp_x; | |
auto& disp_y = app_data.disp_y; | |
auto& attrib_loc_position = app_data.attrib_loc_position; | |
auto& window = app_data.window; | |
auto& prog_id = app_data.prog_id; | |
if(vbo_id != 0) | |
{ | |
glDeleteBuffers(1,&vbo_id); | |
} | |
// create buffers | |
float dx = input_x; | |
float dy = input_y; | |
GLfloat list_vx[] = { | |
ToNDCX(0+dx,win_width), ToNDCY(0+dy,win_height), 0.0, 1.0, // tl | |
ToNDCX(0+dx,win_width), ToNDCY(input_s+dy,win_height), 0.0, 1.0, // bl | |
ToNDCX(input_s+dx,win_width), ToNDCY(input_s+dy,win_height), 0.0, 1.0, // br | |
ToNDCX(0+dx,win_width), ToNDCY(0+dy,win_height), 0.0, 1.0, // tl | |
ToNDCX(input_s+dx,win_width), ToNDCY(input_s+dy,win_height), 0.0, 1.0, // br | |
ToNDCX(input_s+dx,win_width), ToNDCY(0+dy,win_height), 0.0, 1.0 // tr | |
}; | |
rads += (6.28f/300.0f)*1.25f; | |
disp_x = win_width/2 + sin(rads)*200; | |
disp_y = win_height/2 + sin(rads*0.5)*400; | |
glGenBuffers(1,&vbo_id); | |
glBindBuffer(GL_ARRAY_BUFFER,vbo_id); | |
glBufferData(GL_ARRAY_BUFFER, | |
4*6*sizeof(GLfloat), | |
list_vx, | |
GL_STREAM_DRAW); | |
// clear color buffer | |
glViewport(0,0,win_width,win_height); | |
glClear(GL_COLOR_BUFFER_BIT); | |
// render tri | |
glUseProgram(prog_id); | |
glEnableVertexAttribArray(attrib_loc_position); | |
glBindBuffer(GL_ARRAY_BUFFER,vbo_id); | |
glVertexAttribPointer(attrib_loc_position,4,GL_FLOAT,GL_FALSE,0,nullptr); | |
glDrawArrays(GL_TRIANGLES,0,6); | |
glDisableVertexAttribArray(attrib_loc_position); | |
SDL_GL_SwapWindow(window); | |
} | |
void Cleanup(SDL_GLContext &context, | |
GLuint prog_id, | |
GLuint vbo_id) | |
{ | |
glUseProgram(0); | |
glDeleteProgram(prog_id); | |
glDeleteBuffers(1,&vbo_id); | |
SDL_GL_DeleteContext(context); | |
SDL_Quit(); | |
} | |
int main(int argc, char *argv[]) | |
{ | |
ApplicationData app_data; | |
InitSDL(app_data.window,app_data.gl_context,app_data.win_width,app_data.win_height); | |
InitGL(app_data.prog_id,app_data.vbo_id,app_data.attrib_loc_position); | |
// poll for events from the window | |
SDL_Event event; | |
bool keep_running=true; | |
while(keep_running) | |
{ | |
// drain all available events | |
while(SDL_PollEvent(&event) != 0) { | |
if(event.type == SDL_QUIT) { | |
keep_running=false; | |
break; | |
} | |
// else if(event.type == SDL_MOUSEMOTION) | |
// { | |
// app_data.input_x = event.motion.x; | |
// app_data.input_y = event.motion.y; | |
// } | |
else if(event.type == SDL_FINGERMOTION) | |
{ | |
app_data.input_x = event.tfinger.x*app_data.win_width; | |
app_data.input_y = event.tfinger.y*app_data.win_height; | |
} | |
} | |
Render(app_data); | |
} | |
Cleanup(app_data.gl_context,app_data.prog_id,app_data.vbo_id); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment