#include "Shader.h" #include "Utils.h" #include #include "Wrapper.h" Shader::Shader() { unifProjMatrix = Engine::getUniformLocation("projMatrix"); unifViewMatrix = Engine::getUniformLocation("viewMatrix"); unifModelMatrix = Engine::getUniformLocation("modelMatrix"); unifUseTexture = Engine::getUniformLocation("useTexture"); unifUseColor = Engine::getUniformLocation("useColor"); unifUseMixColor = Engine::getUniformLocation("useMixColor"); unifMixColorLoc = Engine::getUniformLocation("mixColor"); unifUseNormals = Engine::getUniformLocation("useNormals"); } Shader::Shader(const Shader& orig) { } Shader::~Shader() { } void Shader::set3DMode(float lag) { float tan = tanf((0.5f * fovY) * M_PI / 180.0f); float q = 1.0f / tan; float aspect = (float) Engine::getWidth() / Engine::getHeight(); proj.set(0, 0, q / aspect); proj.set(1, 1, q); proj.set(2, 2, (nearClip + farClip) / (nearClip - farClip)); proj.set(3, 2, -1.0f); proj.set(2, 3, (2.0f * nearClip * farClip) / (nearClip - farClip)); proj.set(3, 3, 0); Engine::setMatrix(unifProjMatrix, proj.getValues()); // ------------------------------------------------------------------------- // calculate vectors for the view matrix // ------------------------------------------------------------------------- // front front.setAngles(interpolate(lag, oldLengthAngle, lengthAngle), interpolate(lag, oldWidthAngle, widthAngle)); // back back.setInverse(front); // right right.set(front); right.cross(0.0f, 1.0f, 0.0f); right.normalize(); // left left.setInverse(right); // up up.set(front); up.cross(left); up.normalize(); // down down.setInverse(up); Vector3D interCamera = oldCamera; interCamera.addMul(camera, lag); interCamera.addMul(oldCamera, -lag); view.set(0, 0, right.getX()); view.set(0, 1, right.getY()); view.set(0, 2, right.getZ()); view.set(0, 3, right.dotInverse(interCamera)); view.set(1, 0, up.getX()); view.set(1, 1, up.getY()); view.set(1, 2, up.getZ()); view.set(1, 3, up.dotInverse(interCamera)); view.set(2, 0, back.getX()); view.set(2, 1, back.getY()); view.set(2, 2, back.getZ()); view.set(2, 3, back.dotInverse(interCamera)); view.set(3, 0, 0.0f); view.set(3, 1, 0.0f); view.set(3, 0, 0.0f); view.set(3, 3, 1.0f); // ------------------------------------------------------------------------- // update frustum planes // ------------------------------------------------------------------------- // http://cgvr.informatik.uni-bremen.de/teaching/cg_literatur/lighthouse3d_view_frustum_culling/index.html float nearHigh = tan * nearClip; float nearWidth = nearHigh * aspect; float farHigh = tan * farClip; float farWidth = farHigh * aspect; Vector3D fc = interCamera; fc.addMul(front, farClip); Vector3D ftl = fc; ftl.addMul(left, farWidth); ftl.addMul(up, farHigh); Vector3D fbl = fc; fbl.addMul(left, farWidth); fbl.addMul(down, farHigh); Vector3D fbr = fc; fbr.addMul(right, farWidth); fbr.addMul(down, farHigh); Vector3D nc = interCamera; nc.addMul(front, nearClip); Vector3D ntl = nc; ntl.addMul(left, nearWidth); ntl.addMul(down, nearHigh); Vector3D ntr = nc; ntr.addMul(right, nearWidth); ntr.addMul(up, nearHigh); Vector3D nbr = nc; nbr.addMul(right, nearWidth); nbr.addMul(down, nearHigh); // generating planes with counter clockwise vector order frustumPlanes[0].set(fbl, ftl, fbr); // far frustumPlanes[1].set(ntl, ftl, fbl); // left frustumPlanes[2].set(fbr, ntr, nbr); // right frustumPlanes[3].set(fbl, fbr, nbr); // bottom frustumPlanes[4].set(ntr, ftl, ntl); // top frustumPlanes[5].set(nbr, ntr, ntl); // near // ------------------------------------------------------------------------- // calculate vectors for movement // ------------------------------------------------------------------------- // front front.setY(0.0f); front.normalize(); // back back.setInverse(front); // right right.set(front); right.cross(0.0f, 1.0f, 0.0f); right.normalize(); // left left.setInverse(right); // up up.set(0.0f, 1.0f, 0.0f); // down down.setInverse(up); Engine::setMatrix(unifViewMatrix, view.getValues()); } void Shader::set2DMode() { proj.setToIdentity(); Engine::setMatrix(unifProjMatrix, proj.getValues()); int scale = Engine::getScale(); view.set(0, 0, (2.0f * scale) / Engine::getWidth()); view.set(0, 1, 0.0f); view.set(0, 2, 0.0f); view.set(0, 3, -1.0f); view.set(1, 0, 0.0f); view.set(1, 1, (-2.0f * scale) / Engine::getHeight()); view.set(1, 2, 0.0f); view.set(1, 3, 1.0f); view.set(2, 0, 0.0f); view.set(2, 1, 0.0f); view.set(2, 2, (-1.0f * scale) / Engine::getHeight()); view.set(2, 3, 0.5f); view.set(3, 0, 0.0f); view.set(3, 1, 0.0f); view.set(3, 0, 0.0f); view.set(3, 3, 1.0f); Engine::setMatrix(unifViewMatrix, view.getValues()); } void Shader::storeCamera() { oldCamera.set(camera); oldLengthAngle = lengthAngle; oldWidthAngle = widthAngle; } void Shader::setCamera(float x, float y, float z, float length, float width) { camera.set(x, y, z); lengthAngle = length; widthAngle = width; } bool Shader::isInFrustum(float x, float y, float z, float x2, float y2, float z2) const { //return true; // http://cgvr.informatik.uni-bremen.de/teaching/cg_literatur/lighthouse3d_view_frustum_culling/index.html // for each plane do ... for(int fp = 0; fp < 6; fp++) { // reset counters for corners in and out int out = 0; int in = 0; // for each corner of the box do ... // get out of the cycle as soon as a box as corners // both inside and out of the frustum for(int i = 0; i < 8 && (in == 0 || out == 0); i++) { // is the corner outside or inside if(frustumPlanes[fp].getSignedDistance(((i >> 2) & 1) ? x : x2, ((i >> 1) & 1) ? y : y2, (i & 1) ? z : z2) > 0) { out++; } else { in++; } } //if all corners are out if(in == 0) { return false; } } return true; } const Vector3D& Shader::getFront() const { return front; } const Vector3D& Shader::getBack() const { return back; } const Vector3D& Shader::getRight() const { return right; } const Vector3D& Shader::getLeft() const { return left; } const Vector3D& Shader::getUp() const { return up; } const Vector3D& Shader::getDown() const { return down; } void Shader::setTextureEnabled(bool use) { Engine::setInt(unifUseTexture, use); } void Shader::setColorEnabled(bool use) { Engine::setInt(unifUseColor, use); } void Shader::setMixColorEnabled(bool use) { Engine::setInt(unifUseMixColor, use); } void Shader::setMixColor(float r, float g, float b, float a) { Engine::setFloat(unifUseMixColor, r, g, b, a); } void Shader::setTextMode() { setTextureEnabled(true); setColorEnabled(true); setUseBlending(true); setMixColorEnabled(false); setNormalsEnabled(false); } void Shader::setNormalsEnabled(bool use) { Engine::setInt(unifUseNormals, use); } void Shader::setUseBlending(bool use) { if(use) { glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBlendEquation(GL_FUNC_ADD); } else { glDisable(GL_BLEND); } } void Shader::pop() { model.pop(); } void Shader::push() { model.push(); } void Shader::setToIdentity() { model.get().setToIdentity(); } void Shader::scale(float sx, float sy, float sz) { model.get().scale(sx, sy, sz); } void Shader::translate(float tx, float ty, float tz) { model.get().translate(tx, ty, tz); } void Shader::translateX(float tx) { model.get().translateX(tx); } void Shader::translateY(float ty) { model.get().translateY(ty); } void Shader::translateZ(float tz) { model.get().translateZ(tz); } void Shader::translateTo(float tx, float ty, float tz) { model.get().translateTo(tx, ty, tz); } void Shader::rotate(float xDegrees, float yDegrees, float zDegrees) { model.get().rotate(xDegrees, yDegrees, zDegrees); } void Shader::rotateX(float degrees) { model.get().rotateX(degrees); } void Shader::rotateY(float degrees) { model.get().rotateY(degrees); } void Shader::rotateZ(float degrees) { model.get().rotateZ(degrees); } void Shader::updateModelMatrix() { Engine::setMatrix(unifModelMatrix, model.get().getValues()); }