void Renderer::setupProjection(ALLEGRO_TRANSFORM *m) { int dw = al_get_display_width(dpy_); int dh = al_get_display_height(dpy_); // al_perspective_transform(m, -180 * dw / dh, -180, 1, // 180 * dw / dh, 180, 1000); // al_perspective_transform(m, -500, -500, 1, // 500, 500, 10000); double zNear = 0.5, zFar = 1000.0, fov = 90.0, aspect = dw / dh; double left, right; double bottom, top; top = tan (fov*ALLEGRO_PI/360.0)*zNear; bottom = -top; left = aspect*bottom; right = aspect*top; //NBT_Debug("rect: %f %f %f %f", left, top, right, bottom); al_perspective_transform(m, left, top, zNear, right, bottom, zFar); al_set_projection_transform(dpy_, m); }
bool _al_opengl_set_blender(ALLEGRO_DISPLAY *ogl_disp) { int op, src_color, dst_color, op_alpha, src_alpha, dst_alpha; const int blend_modes[8] = { GL_ZERO, GL_ONE, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_SRC_COLOR, GL_DST_COLOR, GL_ONE_MINUS_SRC_COLOR, GL_ONE_MINUS_DST_COLOR }; const int blend_equations[3] = { GL_FUNC_ADD, GL_FUNC_SUBTRACT, GL_FUNC_REVERSE_SUBTRACT }; (void)ogl_disp; al_get_separate_blender(&op, &src_color, &dst_color, &op_alpha, &src_alpha, &dst_alpha); /* glBlendFuncSeparate was only included with OpenGL 1.4 */ /* (And not in OpenGL ES) */ #if !defined ALLEGRO_GP2XWIZ #if !defined ALLEGRO_IPHONE && !defined ALLEGRO_ANDROID if (ogl_disp->ogl_extras->ogl_info.version >= _ALLEGRO_OPENGL_VERSION_1_4) { #else if (ogl_disp->ogl_extras->ogl_info.version >= _ALLEGRO_OPENGL_VERSION_2_0) { #endif glEnable(GL_BLEND); glBlendFuncSeparate(blend_modes[src_color], blend_modes[dst_color], blend_modes[src_alpha], blend_modes[dst_alpha]); if (ogl_disp->ogl_extras->ogl_info.version >= _ALLEGRO_OPENGL_VERSION_2_0) { glBlendEquationSeparate( blend_equations[op], blend_equations[op_alpha]); } else { glBlendEquation(blend_equations[op]); } } else { if (src_color == src_alpha && dst_color == dst_alpha) { glEnable(GL_BLEND); glBlendFunc(blend_modes[src_color], blend_modes[dst_color]); } else { ALLEGRO_ERROR("Blender unsupported with this OpenGL version (%d %d %d %d %d %d)\n", op, src_color, dst_color, op_alpha, src_alpha, dst_alpha); return false; } } #else glEnable(GL_BLEND); glBlendFunc(blend_modes[src_color], blend_modes[dst_color]); #endif return true; } /* These functions make drawing calls use shaders or the fixed pipeline * based on what the user has set up. FIXME: OpenGL only right now. */ static void vert_ptr_on(ALLEGRO_DISPLAY *display, int n, GLint t, int stride, void *v) { /* Only use this shader stuff with GLES2+ or equivalent */ if (display->flags & ALLEGRO_USE_PROGRAMMABLE_PIPELINE) { #ifndef ALLEGRO_CFG_NO_GLES2 if (display->ogl_extras->pos_loc >= 0) { glVertexAttribPointer(display->ogl_extras->pos_loc, n, t, false, stride, v); glEnableVertexAttribArray(display->ogl_extras->pos_loc); } #endif } else { glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(n, t, stride, v); } } static void vert_ptr_off(ALLEGRO_DISPLAY *display) { if (display->flags & ALLEGRO_USE_PROGRAMMABLE_PIPELINE) { #ifndef ALLEGRO_CFG_NO_GLES2 if (display->ogl_extras->pos_loc >= 0) { glDisableVertexAttribArray(display->ogl_extras->pos_loc); } #endif } else { glDisableClientState(GL_VERTEX_ARRAY); } } static void color_ptr_on(ALLEGRO_DISPLAY *display, int n, GLint t, int stride, void *v) { if (display->flags & ALLEGRO_USE_PROGRAMMABLE_PIPELINE) { #ifndef ALLEGRO_CFG_NO_GLES2 if (display->ogl_extras->color_loc >= 0) { glVertexAttribPointer(display->ogl_extras->color_loc, n, t, false, stride, v); glEnableVertexAttribArray(display->ogl_extras->color_loc); } #endif } else { glEnableClientState(GL_COLOR_ARRAY); glColorPointer(n, t, stride, v); } } static void color_ptr_off(ALLEGRO_DISPLAY *display) { if (display->flags & ALLEGRO_USE_PROGRAMMABLE_PIPELINE) { #ifndef ALLEGRO_CFG_NO_GLES2 if (display->ogl_extras->color_loc >= 0) { glDisableVertexAttribArray(display->ogl_extras->color_loc); } #endif } else { glDisableClientState(GL_COLOR_ARRAY); } } static void tex_ptr_on(ALLEGRO_DISPLAY *display, int n, GLint t, int stride, void *v) { if (display->flags & ALLEGRO_USE_PROGRAMMABLE_PIPELINE) { #ifndef ALLEGRO_CFG_NO_GLES2 if (display->ogl_extras->texcoord_loc >= 0) { glVertexAttribPointer(display->ogl_extras->texcoord_loc, n, t, false, stride, v); glEnableVertexAttribArray(display->ogl_extras->texcoord_loc); } #endif } else { glEnableClientState(GL_TEXTURE_COORD_ARRAY); glTexCoordPointer(n, t, stride, v); } } static void tex_ptr_off(ALLEGRO_DISPLAY *display) { if (display->flags & ALLEGRO_USE_PROGRAMMABLE_PIPELINE) { #ifndef ALLEGRO_CFG_NO_GLES2 if (display->ogl_extras->texcoord_loc >= 0) { glDisableVertexAttribArray(display->ogl_extras->texcoord_loc); } #endif } else { glDisableClientState(GL_TEXTURE_COORD_ARRAY); } } /* Dummy implementation of clear. */ static void ogl_clear(ALLEGRO_DISPLAY *d, ALLEGRO_COLOR *color) { ALLEGRO_DISPLAY *ogl_disp = (void *)d; ALLEGRO_BITMAP *target = al_get_target_bitmap(); ALLEGRO_BITMAP_EXTRA_OPENGL *ogl_target; float r, g, b, a; if (target->parent) target = target->parent; ogl_target = target->extra; if ((!ogl_target->is_backbuffer && ogl_disp->ogl_extras->opengl_target != target) || target->locked) { _al_clear_memory(color); return; } al_unmap_rgba_f(*color, &r, &g, &b, &a); /* There's a very nasty bug in Android 2.1 that makes glClear cause * screen flicker (appears to me it's swapping buffers.) Work around * by drawing two triangles instead on that OS. */ #ifdef ALLEGRO_ANDROID if (ogl_target->is_backbuffer && _al_android_is_os_2_1()) { GLfloat v[8] = { 0, d->h, 0, 0, d->w, d->h, d->w, 0 }; GLfloat c[16] = { r, g, b, a, r, g, b, a, r, g, b, a, r, g, b, a }; ALLEGRO_TRANSFORM bak1, bak2, t; al_copy_transform(&bak1, &d->proj_transform); al_copy_transform(&bak2, al_get_current_transform()); al_identity_transform(&t); al_ortho_transform(&t, 0, d->w, d->h, 0, -1, 1); al_set_projection_transform(d, &t); al_identity_transform(&t); al_use_transform(&t); _al_opengl_set_blender(d); vert_ptr_on(d, 2, GL_FLOAT, 2*sizeof(float), v); color_ptr_on(d, 4, GL_FLOAT, 4*sizeof(float), c); if (!(d->flags & ALLEGRO_USE_PROGRAMMABLE_PIPELINE)) { glDisableClientState(GL_NORMAL_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); } glDisable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, 0); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); vert_ptr_off(d); color_ptr_off(d); al_set_projection_transform(d, &bak1); al_use_transform(&bak2); return; } #endif glClearColor(r, g, b, a); glClear(GL_COLOR_BUFFER_BIT); }
void Renderer::run() { NBT_Debug("begin"); al_hide_mouse_cursor(dpy_); al_identity_transform(&camera_transform_); float x = -camera_pos_.x, y = -camera_pos_.y, z = -camera_pos_.z; //x = -dim0_->spawnX(); //z = -dim0_->spawnZ(); al_translate_transform_3d(&camera_transform_, x, y, z); al_rotate_transform_3d(&camera_transform_, 0.0, 1.0, 0.0, DEG_TO_RAD(180)); memset(key_state_, 0, sizeof(key_state_) * sizeof(key_state_[0])); al_start_timer(tmr_); NBT_Debug("run!"); //al_use_shader(nullptr); /*ALLEGRO_TRANSFORM trans; al_identity_transform(&trans); al_orthographic_transform(&trans, 0, 0, -1, al_get_display_width(dpy_), al_get_display_height(dpy_), 1); al_set_projection_transform(dpy_, &trans); al_identity_transform(&trans); al_use_transform(&trans); if(!resManager_->getAtlas()->getSheet(0)->alBitmap()) NBT_Debug("no sheet bitmap????"); */ //al_draw_bitmap(resManager_->getAtlas()->getSheet(0)->alBitmap(), 0, 0, 0); //al_flip_display(); //sleep(10); bool redraw = false; bool doUpdateLookPos = false; bool cleared = false; while(1) { ALLEGRO_EVENT ev; al_wait_for_event(queue_, &ev); if(ev.type == ALLEGRO_EVENT_TIMER) { redraw = true; //cam_.rx = 1.0; float x = 0.0, y = 0.0, z = 0.0; float translate_diff = 0.3; float ry = 0.0; float rotate_diff = 0.04; bool changeTranslation = false; bool changeRotation = false; if(key_state_[ALLEGRO_KEY_W]) { z += translate_diff; changeTranslation = true; } if(key_state_[ALLEGRO_KEY_S]) { z -= translate_diff; changeTranslation = true; } if(key_state_[ALLEGRO_KEY_A]) { x += translate_diff; changeTranslation = true; } if(key_state_[ALLEGRO_KEY_D]) { x -= translate_diff; changeTranslation = true; } if(key_state_[ALLEGRO_KEY_SPACE]) { y -= translate_diff; changeTranslation = true; } if(key_state_[ALLEGRO_KEY_LSHIFT]) { y += translate_diff; changeTranslation = true; } if(key_state_[ALLEGRO_KEY_LEFT]) { ry += rotate_diff; changeRotation = true; } if(key_state_[ALLEGRO_KEY_RIGHT]) { ry -= rotate_diff; changeRotation = true; } if(changeTranslation) { //camera_pos_.translate(x, y, z); al_translate_transform_3d(&camera_transform_, x, y, z); doUpdateLookPos = true; } if(changeRotation) { al_rotate_transform_3d(&camera_transform_, 0.0, 1.0, 0.0, ry); doUpdateLookPos = true; } if(doUpdateLookPos) updateLookPos(); } else if(ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE) { NBT_Debug("display close"); break; } else if(ev.type == ALLEGRO_EVENT_KEY_DOWN) { //NBT_Debug("key down"); //NBT_Debug("pos: %fx%f", -camera_transform_.m[2][0], -camera_transform_.m[2][2]); key_state_[ev.keyboard.keycode] = true; if (ev.keyboard.keycode == ALLEGRO_KEY_Q) { break; } else if(ev.keyboard.keycode == ALLEGRO_KEY_C) { NBT_Debug("CLEAR CHUNKS"); glBindVertexArray(vao_); for(auto ch: chunkData_) { delete ch.second; } glBindVertexArray(0); chunkData_.clear(); glDeleteBuffers(1, &vao_); cleared = true; } else if (ev.keyboard.keycode == ALLEGRO_KEY_ESCAPE) { grab_mouse_ = !grab_mouse_; } } else if(ev.type == ALLEGRO_EVENT_KEY_UP) { //NBT_Debug("pos: %fx%f", -camera_transform_.m[2][0], -camera_transform_.m[2][2]); key_state_[ev.keyboard.keycode] = false; } else if(ev.type == ALLEGRO_EVENT_MOUSE_BUTTON_UP) { grab_mouse_ = true; } else if(ev.type == ALLEGRO_EVENT_MOUSE_AXES && grab_mouse_) { float dx = ev.mouse.dx, dy = ev.mouse.dy; if(dy > 0 && dy < 1.5) dy = 0.0; if(dy < 0 && dy > -1.5) dy = 0.0; if(dx > 0 && dx < 1.5) dy = 0.0; if(dx < 0 && dx > -1.5) dx = 0.0; float ry = dx / al_get_display_width(dpy_), rx = dy / al_get_display_height(dpy_); rx_look += rx; al_rotate_transform_3d(&camera_transform_, 0.0, 1.0, 0.0, ry); // al_rotate_transform_3d(&camera_transform_, 1.0, 0.0, 0.0, rx); //cam_.rx += dy / al_get_display_height(dpy_); al_set_mouse_xy(dpy_, al_get_display_width(dpy_)/2.0, al_get_display_height(dpy_)/2.0); doUpdateLookPos = true; } if(redraw && al_is_event_queue_empty(queue_)) { if(!loadChunkQueue.empty()) { NBT_Debug("%i chunks to load", loadChunkQueue.size()); std::pair<int32_t, int32_t> pos = loadChunkQueue.front(); loadChunkQueue.pop(); processChunk(pos.first, pos.second); } else { if(!cleared) { //NBT_Debug("pos: %fx%fx%f", camera_pos_.getX(), camera_pos_.getZ(), camera_pos_.getY()); autoLoadChunks(camera_pos_.getX() / 16.0, camera_pos_.getZ() / 16.0); } } ALLEGRO_STATE state; al_store_state(&state, ALLEGRO_STATE_ALL); al_set_projection_transform(dpy_, &al_proj_transform_); glClear(GL_DEPTH_BUFFER_BIT); redraw = false; al_clear_to_color(al_map_rgb(255,255,255)); draw(); al_restore_state(&state); al_set_projection_transform(dpy_, &al_proj_transform_); drawHud(); al_restore_state(&state); al_flip_display(); } } NBT_Debug("stop timer"); al_stop_timer(tmr_); NBT_Debug("end"); NBT_Debug("sizeof GL_FLOAT: %i", sizeof(GLfloat)); }