git-svn-id: svn://db.shs.com.ru/libs@47 a8b55f48-bf90-11e4-a774-851b48703e85
This commit is contained in:
@@ -53,6 +53,7 @@ void GLFramebuffer::resize(int width, int height) {
|
|||||||
glTexParameteri(target_, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
glTexParameteri(target_, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
glTexParameteri(target_, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
glTexParameteri(target_, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
glTexParameteri(target_, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
glTexParameteri(target_, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
|
glTexParameteri(target_, GL_TEXTURE_MAX_LEVEL, 4);
|
||||||
glTexParameteri(target_, GL_GENERATE_MIPMAP_SGIS, GL_FALSE);
|
glTexParameteri(target_, GL_GENERATE_MIPMAP_SGIS, GL_FALSE);
|
||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, target_, colors[i], 0);
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, target_, colors[i], 0);
|
||||||
}
|
}
|
||||||
@@ -76,6 +77,13 @@ void GLFramebuffer::resize(int width, int height) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QImage GLFramebuffer::grab() const {
|
||||||
|
//glReadPixels(0, 0, wid, hei, GL_RGBA, );
|
||||||
|
//QImage ret();
|
||||||
|
return QImage();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void GLFramebuffer::bind() {
|
void GLFramebuffer::bind() {
|
||||||
if (is_changed) resize(wid, hei);
|
if (is_changed) resize(wid, hei);
|
||||||
if (fbo == 0) return;
|
if (fbo == 0) return;
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ public:
|
|||||||
int width() const {return wid;}
|
int width() const {return wid;}
|
||||||
int height() const {return hei;}
|
int height() const {return hei;}
|
||||||
QSize size() const {return QSize(wid, hei);}
|
QSize size() const {return QSize(wid, hei);}
|
||||||
|
QImage grab() const;
|
||||||
|
|
||||||
void resize(int width, int height);
|
void resize(int width, int height);
|
||||||
void bind();
|
void bind();
|
||||||
|
|||||||
@@ -208,6 +208,32 @@ void GLObjectBase::render(int * id, QMap<int, GLObjectBase * > * ids, int sh_id_
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Light::Light(): GLObjectBase(), shadow_map(true, 1, GL_R16F) {
|
||||||
|
type_ = GLObjectBase::Light;
|
||||||
|
light_type = Omni;
|
||||||
|
intensity = 1.;
|
||||||
|
angle_start = angle_end = 180.;
|
||||||
|
decay_linear = decay_quadratic = decay_start = 0.;
|
||||||
|
decay_const = decay_end = 1.;
|
||||||
|
direction.setZ(1.);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Light::Light(const QVector3D & p, const QColor & c, GLdouble i): GLObjectBase(), shadow_map(true, 1, GL_R16F) {
|
||||||
|
type_ = GLObjectBase::Light;
|
||||||
|
light_type = Omni;
|
||||||
|
pos_ = p;
|
||||||
|
intensity = i;
|
||||||
|
/*color_ = c;*/
|
||||||
|
angle_start = angle_end = 180.;
|
||||||
|
decay_linear = decay_quadratic = decay_start = 0.;
|
||||||
|
decay_const = decay_end = 1.;
|
||||||
|
direction.setZ(1.);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
GLObjectBase * Light::clone(bool withChildren) {
|
GLObjectBase * Light::clone(bool withChildren) {
|
||||||
Light * o = new Light(*this);
|
Light * o = new Light(*this);
|
||||||
//GLObjectBase::clone(withChildren);
|
//GLObjectBase::clone(withChildren);
|
||||||
@@ -219,12 +245,14 @@ GLObjectBase * Light::clone(bool withChildren) {
|
|||||||
for (int i = 0; i < children_.size(); ++i)
|
for (int i = 0; i < children_.size(); ++i)
|
||||||
o->addChild(children_[i]->clone(withChildren));
|
o->addChild(children_[i]->clone(withChildren));
|
||||||
}
|
}
|
||||||
|
o->light_type = light_type;
|
||||||
o->direction = direction;
|
o->direction = direction;
|
||||||
|
o->angle_start = angle_start;
|
||||||
|
o->angle_end = angle_end;
|
||||||
o->intensity = intensity;
|
o->intensity = intensity;
|
||||||
o->decay_const = decay_const;
|
o->decay_const = decay_const;
|
||||||
o->decay_linear = decay_linear;
|
o->decay_linear = decay_linear;
|
||||||
o->decay_quadratic = decay_quadratic;
|
o->decay_quadratic = decay_quadratic;
|
||||||
o->light_type = light_type;
|
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -214,15 +214,15 @@ class Light: public GLObjectBase {
|
|||||||
public:
|
public:
|
||||||
enum Type {Omni, Directional, Cone};
|
enum Type {Omni, Directional, Cone};
|
||||||
|
|
||||||
Light(): GLObjectBase(), shadow_map(true, 1, GL_R16F) {type_ = GLObjectBase::Light; light_type = Omni; intensity = 1.; decay_linear = decay_quadratic = angle_spread = angle_decay_exp = decay_start = 0.; decay_const = decay_end = 1.; direction.setZ(1.);}
|
Light();
|
||||||
Light(const QVector3D & p, const QColor & c = Qt::white, GLdouble i = 1.): GLObjectBase(), shadow_map(true, 1, GL_R16F) {type_ = GLObjectBase::Light; light_type = Omni; pos_ = p; intensity = i; /*color_ = c;*/ decay_linear = decay_quadratic = angle_spread = angle_decay_exp = decay_start = 0.; decay_const = decay_end = 1.; direction.setZ(1.);}
|
Light(const QVector3D & p, const QColor & c = Qt::white, GLdouble i = 1.);
|
||||||
virtual GLObjectBase * clone(bool withChildren = true);
|
virtual GLObjectBase * clone(bool withChildren = true);
|
||||||
virtual void init() {shadow_map.resize(512, 512); is_init = true;}
|
virtual void init() {shadow_map.resize(512, 512); is_init = true;}
|
||||||
virtual void draw(QGLShaderProgram * prog, bool simplest = false);
|
virtual void draw(QGLShaderProgram * prog, bool simplest = false);
|
||||||
|
|
||||||
QVector3D direction;
|
QVector3D direction;
|
||||||
GLdouble angle_spread;
|
GLdouble angle_start;
|
||||||
GLdouble angle_decay_exp;
|
GLdouble angle_end;
|
||||||
GLdouble intensity;
|
GLdouble intensity;
|
||||||
GLdouble decay_const;
|
GLdouble decay_const;
|
||||||
GLdouble decay_linear;
|
GLdouble decay_linear;
|
||||||
|
|||||||
@@ -74,8 +74,8 @@ void GLObjectEditor::setObject(GLObjectBase * o) {
|
|||||||
spinLightDecayConst->setValue(l->decay_const);
|
spinLightDecayConst->setValue(l->decay_const);
|
||||||
spinLightDecayLinear->setValue(l->decay_linear);
|
spinLightDecayLinear->setValue(l->decay_linear);
|
||||||
spinLightDecayQuadratic->setValue(l->decay_quadratic);
|
spinLightDecayQuadratic->setValue(l->decay_quadratic);
|
||||||
spinLightAngleSpread->setValue(l->angle_spread);
|
spinLightAngleStart->setValue(l->angle_start);
|
||||||
spinLightAngleDecayExp->setValue(l->angle_decay_exp);
|
spinLightAngleEnd->setValue(l->angle_end);
|
||||||
spinLightDirectionX->setValue(l->direction.x());
|
spinLightDirectionX->setValue(l->direction.x());
|
||||||
spinLightDirectionY->setValue(l->direction.y());
|
spinLightDirectionY->setValue(l->direction.y());
|
||||||
spinLightDirectionZ->setValue(l->direction.z());
|
spinLightDirectionZ->setValue(l->direction.z());
|
||||||
@@ -111,9 +111,21 @@ void GLObjectEditor::objectChanged() {
|
|||||||
l->decay_const = spinLightDecayConst->value();
|
l->decay_const = spinLightDecayConst->value();
|
||||||
l->decay_linear = spinLightDecayLinear->value();
|
l->decay_linear = spinLightDecayLinear->value();
|
||||||
l->decay_quadratic = spinLightDecayQuadratic->value();
|
l->decay_quadratic = spinLightDecayQuadratic->value();
|
||||||
l->angle_spread = spinLightAngleSpread->value();
|
l->angle_start = spinLightAngleStart->value();
|
||||||
l->angle_decay_exp = spinLightAngleDecayExp->value();
|
l->angle_end = spinLightAngleEnd->value();
|
||||||
l->direction = QVector3D(spinLightDirectionX->value(), spinLightDirectionY->value(), spinLightDirectionZ->value()).normalized();
|
l->direction = QVector3D(spinLightDirectionX->value(), spinLightDirectionY->value(), spinLightDirectionZ->value()).normalized();
|
||||||
}
|
}
|
||||||
emit changed();
|
emit changed();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void GLObjectEditor::on_spinLightAngleStart_valueChanged(double v) {
|
||||||
|
if (spinLightAngleEnd->value() < v)
|
||||||
|
spinLightAngleEnd->setValue(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void GLObjectEditor::on_spinLightAngleEnd_valueChanged(double v) {
|
||||||
|
if (spinLightAngleStart->value() > v)
|
||||||
|
spinLightAngleStart->setValue(v);
|
||||||
|
}
|
||||||
|
|||||||
@@ -39,6 +39,8 @@ protected:
|
|||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void objectChanged();
|
void objectChanged();
|
||||||
|
void on_spinLightAngleStart_valueChanged(double v);
|
||||||
|
void on_spinLightAngleEnd_valueChanged(double v);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void changed();
|
void changed();
|
||||||
|
|||||||
@@ -364,6 +364,12 @@
|
|||||||
<property name="decimals">
|
<property name="decimals">
|
||||||
<number>2</number>
|
<number>2</number>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="singleStep">
|
||||||
|
<double>0.100000000000000</double>
|
||||||
|
</property>
|
||||||
|
<property name="pageStep">
|
||||||
|
<double>1.000000000000000</double>
|
||||||
|
</property>
|
||||||
<property name="squareScale">
|
<property name="squareScale">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
@@ -390,6 +396,12 @@
|
|||||||
<property name="decimals">
|
<property name="decimals">
|
||||||
<number>2</number>
|
<number>2</number>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="singleStep">
|
||||||
|
<double>0.100000000000000</double>
|
||||||
|
</property>
|
||||||
|
<property name="pageStep">
|
||||||
|
<double>1.000000000000000</double>
|
||||||
|
</property>
|
||||||
<property name="squareScale">
|
<property name="squareScale">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
@@ -416,6 +428,12 @@
|
|||||||
<property name="decimals">
|
<property name="decimals">
|
||||||
<number>2</number>
|
<number>2</number>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="singleStep">
|
||||||
|
<double>0.100000000000000</double>
|
||||||
|
</property>
|
||||||
|
<property name="pageStep">
|
||||||
|
<double>1.000000000000000</double>
|
||||||
|
</property>
|
||||||
<property name="squareScale">
|
<property name="squareScale">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
@@ -442,6 +460,12 @@
|
|||||||
<property name="decimals">
|
<property name="decimals">
|
||||||
<number>2</number>
|
<number>2</number>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="singleStep">
|
||||||
|
<double>0.100000000000000</double>
|
||||||
|
</property>
|
||||||
|
<property name="pageStep">
|
||||||
|
<double>1.000000000000000</double>
|
||||||
|
</property>
|
||||||
<property name="squareScale">
|
<property name="squareScale">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
@@ -450,52 +474,52 @@
|
|||||||
<item row="6" column="0">
|
<item row="6" column="0">
|
||||||
<widget class="QLabel" name="label_18">
|
<widget class="QLabel" name="label_18">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Angle Spread</string>
|
<string>Angle Start</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="6" column="1">
|
<item row="6" column="1">
|
||||||
<widget class="SpinSlider" name="spinLightAngleSpread">
|
<widget class="SpinSlider" name="spinLightAngleStart">
|
||||||
<property name="minimum">
|
<property name="minimum">
|
||||||
<double>0.000000000000000</double>
|
<double>0.000000000000000</double>
|
||||||
</property>
|
</property>
|
||||||
<property name="maximum">
|
<property name="maximum">
|
||||||
<double>90.000000000000000</double>
|
<double>180.000000000000000</double>
|
||||||
</property>
|
|
||||||
<property name="value">
|
|
||||||
<double>45.000000000000000</double>
|
|
||||||
</property>
|
</property>
|
||||||
<property name="decimals">
|
<property name="decimals">
|
||||||
<number>1</number>
|
<number>1</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="squareScale">
|
<property name="singleStep">
|
||||||
<bool>false</bool>
|
<double>5.000000000000000</double>
|
||||||
|
</property>
|
||||||
|
<property name="pageStep">
|
||||||
|
<double>30.000000000000000</double>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="7" column="0">
|
<item row="7" column="0">
|
||||||
<widget class="QLabel" name="label_19">
|
<widget class="QLabel" name="label_19">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Angle decay exp</string>
|
<string>Angle End</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="7" column="1">
|
<item row="7" column="1">
|
||||||
<widget class="SpinSlider" name="spinLightAngleDecayExp">
|
<widget class="SpinSlider" name="spinLightAngleEnd">
|
||||||
<property name="minimum">
|
<property name="minimum">
|
||||||
<double>0.000000000000000</double>
|
<double>0.000000000000000</double>
|
||||||
</property>
|
</property>
|
||||||
<property name="maximum">
|
<property name="maximum">
|
||||||
<double>64.000000000000000</double>
|
<double>180.000000000000000</double>
|
||||||
</property>
|
|
||||||
<property name="value">
|
|
||||||
<double>1.000000000000000</double>
|
|
||||||
</property>
|
</property>
|
||||||
<property name="decimals">
|
<property name="decimals">
|
||||||
<number>2</number>
|
<number>1</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="squareScale">
|
<property name="singleStep">
|
||||||
<bool>true</bool>
|
<double>5.000000000000000</double>
|
||||||
|
</property>
|
||||||
|
<property name="pageStep">
|
||||||
|
<double>30.000000000000000</double>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@@ -520,6 +544,12 @@
|
|||||||
<property name="decimals">
|
<property name="decimals">
|
||||||
<number>2</number>
|
<number>2</number>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="singleStep">
|
||||||
|
<double>0.100000000000000</double>
|
||||||
|
</property>
|
||||||
|
<property name="pageStep">
|
||||||
|
<double>1.000000000000000</double>
|
||||||
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="9" column="0">
|
<item row="9" column="0">
|
||||||
@@ -550,6 +580,12 @@
|
|||||||
<property name="decimals">
|
<property name="decimals">
|
||||||
<number>2</number>
|
<number>2</number>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="singleStep">
|
||||||
|
<double>0.100000000000000</double>
|
||||||
|
</property>
|
||||||
|
<property name="pageStep">
|
||||||
|
<double>1.000000000000000</double>
|
||||||
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="10" column="1">
|
<item row="10" column="1">
|
||||||
@@ -566,6 +602,12 @@
|
|||||||
<property name="decimals">
|
<property name="decimals">
|
||||||
<number>2</number>
|
<number>2</number>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="singleStep">
|
||||||
|
<double>0.100000000000000</double>
|
||||||
|
</property>
|
||||||
|
<property name="pageStep">
|
||||||
|
<double>1.000000000000000</double>
|
||||||
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
@@ -940,7 +982,7 @@
|
|||||||
</hints>
|
</hints>
|
||||||
</connection>
|
</connection>
|
||||||
<connection>
|
<connection>
|
||||||
<sender>spinLightAngleSpread</sender>
|
<sender>spinLightAngleStart</sender>
|
||||||
<signal>valueChanged(double)</signal>
|
<signal>valueChanged(double)</signal>
|
||||||
<receiver>GLObjectEditor</receiver>
|
<receiver>GLObjectEditor</receiver>
|
||||||
<slot>objectChanged()</slot>
|
<slot>objectChanged()</slot>
|
||||||
@@ -956,7 +998,7 @@
|
|||||||
</hints>
|
</hints>
|
||||||
</connection>
|
</connection>
|
||||||
<connection>
|
<connection>
|
||||||
<sender>spinLightAngleDecayExp</sender>
|
<sender>spinLightAngleEnd</sender>
|
||||||
<signal>valueChanged(double)</signal>
|
<signal>valueChanged(double)</signal>
|
||||||
<receiver>GLObjectEditor</receiver>
|
<receiver>GLObjectEditor</receiver>
|
||||||
<slot>objectChanged()</slot>
|
<slot>objectChanged()</slot>
|
||||||
|
|||||||
@@ -56,8 +56,8 @@ void GLRendererBase::setupLight(const Light & l, int inpass_index, int gl_index)
|
|||||||
glLightf(gl_index, GL_QUADRATIC_ATTENUATION, l.decay_quadratic);
|
glLightf(gl_index, GL_QUADRATIC_ATTENUATION, l.decay_quadratic);
|
||||||
if (l.light_type == Light::Cone) {
|
if (l.light_type == Light::Cone) {
|
||||||
glLightfv(gl_index, GL_SPOT_DIRECTION, dir);
|
glLightfv(gl_index, GL_SPOT_DIRECTION, dir);
|
||||||
glLightf(gl_index, GL_SPOT_CUTOFF, l.angle_spread);
|
glLightf(gl_index, GL_SPOT_CUTOFF, l.angle_end / 2.);
|
||||||
glLightf(gl_index, GL_SPOT_EXPONENT, l.angle_decay_exp);
|
glLightf(gl_index, GL_SPOT_EXPONENT, (1. - piClamp<double>((l.angle_end - l.angle_start) / (l.angle_end + 0.001), 0., 1.)) * 128.);
|
||||||
} else {
|
} else {
|
||||||
glLightf(gl_index, GL_SPOT_CUTOFF, 180.);
|
glLightf(gl_index, GL_SPOT_CUTOFF, 180.);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,9 +54,14 @@ const char qgl_uniform[] =
|
|||||||
const char qgl_structs[] =
|
const char qgl_structs[] =
|
||||||
"const int qgl_MaxLights = 16;\n"
|
"const int qgl_MaxLights = 16;\n"
|
||||||
"struct QGLLight {\n"
|
"struct QGLLight {\n"
|
||||||
" vec4 position;\n"
|
|
||||||
" vec4 color;\n"
|
" vec4 color;\n"
|
||||||
|
" vec4 position;\n"
|
||||||
|
" vec4 direction;\n"
|
||||||
" float intensity;\n"
|
" float intensity;\n"
|
||||||
|
" float startAngle;\n"
|
||||||
|
" float startAngleCos;\n"
|
||||||
|
" float endAngle;\n"
|
||||||
|
" float endAngleCos;\n"
|
||||||
" float constantAttenuation;\n"
|
" float constantAttenuation;\n"
|
||||||
" float linearAttenuation;\n"
|
" float linearAttenuation;\n"
|
||||||
" float quadraticAttenuation;\n"
|
" float quadraticAttenuation;\n"
|
||||||
@@ -192,19 +197,31 @@ void setUniformLights(QGLShaderProgram * prog, const QVector<Light*> & lights, c
|
|||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
" vec3 position;\n"
|
" vec3 position;\n"
|
||||||
|
" vec3 direction;\n"
|
||||||
" vec4 color;\n"
|
" vec4 color;\n"
|
||||||
" float intensity;\n"
|
" float intensity;\n"
|
||||||
|
" float startAngle;\n"
|
||||||
|
" float endAngle;\n"
|
||||||
" float constantAttenuation;\n"
|
" float constantAttenuation;\n"
|
||||||
" float linearAttenuation;\n"
|
" float linearAttenuation;\n"
|
||||||
" float quadraticAttenuation;\n"
|
" float quadraticAttenuation;\n"
|
||||||
*/
|
*/
|
||||||
void setUniformLight(QGLShaderProgram * prog, Light * light, QString ulightn, const QMatrix4x4 & mat, const QVector4D & dp) {
|
void setUniformLight(QGLShaderProgram * prog, Light * light, QString ulightn, const QMatrix4x4 & mat, const QVector4D & dp) {
|
||||||
QMatrix4x4 m = mat * light->worldTransform();
|
QMatrix4x4 m = mat * light->worldTransform();
|
||||||
QVector4D pos(0, 0, 0, 1.);
|
QVector4D pos(0, 0, 0, 1.), dir(light->direction);
|
||||||
pos = m * pos;
|
pos = m * pos;
|
||||||
|
dir = (m * dir).normalized();
|
||||||
|
double ang_start = light->angle_start / 2., ang_end = light->angle_end / 2.;
|
||||||
|
if (light->light_type == Light::Omni)
|
||||||
|
ang_start = ang_end = 180.;
|
||||||
//qDebug() << "light" << light->name() << ulightn << pos;
|
//qDebug() << "light" << light->name() << ulightn << pos;
|
||||||
prog->setUniformValue((ulightn + ".position").toLatin1().constData(), pos);
|
prog->setUniformValue((ulightn + ".position").toLatin1().constData(), pos);
|
||||||
|
prog->setUniformValue((ulightn + ".direction").toLatin1().constData(), dir);
|
||||||
prog->setUniformValue((ulightn + ".intensity").toLatin1().constData(), GLfloat(light->intensity));
|
prog->setUniformValue((ulightn + ".intensity").toLatin1().constData(), GLfloat(light->intensity));
|
||||||
|
prog->setUniformValue((ulightn + ".startAngle").toLatin1().constData(), GLfloat(ang_start));
|
||||||
|
prog->setUniformValue((ulightn + ".startAngleCos").toLatin1().constData(), GLfloat(cos(ang_start * deg2rad)));
|
||||||
|
prog->setUniformValue((ulightn + ".endAngle").toLatin1().constData(), GLfloat(ang_end));
|
||||||
|
prog->setUniformValue((ulightn + ".endAngleCos").toLatin1().constData(), GLfloat(cos(ang_end * deg2rad)));
|
||||||
prog->setUniformValue((ulightn + ".color").toLatin1().constData(), light->color());
|
prog->setUniformValue((ulightn + ".color").toLatin1().constData(), light->color());
|
||||||
prog->setUniformValue((ulightn + ".constantAttenuation").toLatin1().constData(), GLfloat(light->decay_const));
|
prog->setUniformValue((ulightn + ".constantAttenuation").toLatin1().constData(), GLfloat(light->decay_const));
|
||||||
prog->setUniformValue((ulightn + ".linearAttenuation").toLatin1().constData(), GLfloat(light->decay_linear));
|
prog->setUniformValue((ulightn + ".linearAttenuation").toLatin1().constData(), GLfloat(light->decay_linear));
|
||||||
|
|||||||
@@ -109,9 +109,14 @@ void createGLTexture(GLuint & tex, int width, int height, const GLenum & format,
|
|||||||
glTexImage2D(target, 0, format, width, height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, 0);
|
glTexImage2D(target, 0, format, width, height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, 0);
|
||||||
else {
|
else {
|
||||||
int t = GL_UNSIGNED_BYTE;
|
int t = GL_UNSIGNED_BYTE;
|
||||||
if (format == GL_RGB32F || format == GL_RGB16F)
|
int f = GL_RGBA;
|
||||||
|
if (format == GL_RGB32F || format == GL_RGB16F || format == GL_RGBA32F || format == GL_RGBA16F)
|
||||||
t = GL_FLOAT;
|
t = GL_FLOAT;
|
||||||
glTexImage2D(target, 0, format, width, height, 0, GL_RGBA, t, 0);
|
if (format == GL_RGB32F || format == GL_RGB16F || format == GL_RGB8 || format == GL_RGB)
|
||||||
|
f = GL_RGB;
|
||||||
|
glTexImage2D(target, 0, format, width, height, 0, f, t, 0);
|
||||||
|
//glGenerateMipmap(target);
|
||||||
|
//qDebug() << "glTexImage2D" << width << height << QString::number(t, 16);
|
||||||
}
|
}
|
||||||
//qDebug() << QString::number(glGetError(), 16);
|
//qDebug() << QString::number(glGetError(), 16);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -142,6 +142,7 @@ void GLVBO::draw(GLenum type, QGLShaderProgram * prog, bool simplest) {
|
|||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, buffer_);
|
glBindBuffer(GL_ARRAY_BUFFER, buffer_);
|
||||||
if (prog) {
|
if (prog) {
|
||||||
|
locs.clear();
|
||||||
glDisableClientState(GL_VERTEX_ARRAY);
|
glDisableClientState(GL_VERTEX_ARRAY);
|
||||||
glDisableClientState(GL_NORMAL_ARRAY);
|
glDisableClientState(GL_NORMAL_ARRAY);
|
||||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||||
@@ -150,21 +151,25 @@ void GLVBO::draw(GLenum type, QGLShaderProgram * prog, bool simplest) {
|
|||||||
glEnableVertexAttribArray(loc);
|
glEnableVertexAttribArray(loc);
|
||||||
glVertexAttribPointer(loc, 3, GL_FLOAT, 0, 0, 0);
|
glVertexAttribPointer(loc, 3, GL_FLOAT, 0, 0, 0);
|
||||||
loc = prog->attributeLocation("qgl_Normal");
|
loc = prog->attributeLocation("qgl_Normal");
|
||||||
|
locs << loc;
|
||||||
if (has_normals) {
|
if (has_normals) {
|
||||||
glEnableVertexAttribArray(loc);
|
glEnableVertexAttribArray(loc);
|
||||||
glVertexAttribPointer(loc, 3, GL_FLOAT, 0, 0, offsets[0]);
|
glVertexAttribPointer(loc, 3, GL_FLOAT, 0, 0, offsets[0]);
|
||||||
|
locs << loc;
|
||||||
} else
|
} else
|
||||||
glDisableVertexAttribArray(loc);
|
glDisableVertexAttribArray(loc);
|
||||||
loc = prog->attributeLocation("qgl_Texture");
|
loc = prog->attributeLocation("qgl_Texture");
|
||||||
if (has_texcoords) {
|
if (has_texcoords) {
|
||||||
glEnableVertexAttribArray(loc);
|
glEnableVertexAttribArray(loc);
|
||||||
glVertexAttribPointer(loc, 2, GL_FLOAT, 0, 0, offsets[1]);
|
glVertexAttribPointer(loc, 2, GL_FLOAT, 0, 0, offsets[1]);
|
||||||
|
locs << loc;
|
||||||
} else
|
} else
|
||||||
glDisableVertexAttribArray(loc);
|
glDisableVertexAttribArray(loc);
|
||||||
loc = prog->attributeLocation("qgl_Color");
|
loc = prog->attributeLocation("qgl_Color");
|
||||||
if (has_colors) {
|
if (has_colors) {
|
||||||
glEnableVertexAttribArray(loc);
|
glEnableVertexAttribArray(loc);
|
||||||
glVertexAttribPointer(loc, 4, GL_FLOAT, 0, 0, offsets[2]);
|
glVertexAttribPointer(loc, 4, GL_FLOAT, 0, 0, offsets[2]);
|
||||||
|
locs << loc;
|
||||||
} else
|
} else
|
||||||
glDisableVertexAttribArray(loc);
|
glDisableVertexAttribArray(loc);
|
||||||
loc = prog->attributeLocation("qgl_Tangent");
|
loc = prog->attributeLocation("qgl_Tangent");
|
||||||
@@ -174,6 +179,7 @@ void GLVBO::draw(GLenum type, QGLShaderProgram * prog, bool simplest) {
|
|||||||
glEnableVertexAttribArray(loc2);
|
glEnableVertexAttribArray(loc2);
|
||||||
glVertexAttribPointer(loc, 3, GL_FLOAT, 0, 0, offsets[3]);
|
glVertexAttribPointer(loc, 3, GL_FLOAT, 0, 0, offsets[3]);
|
||||||
glVertexAttribPointer(loc2, 3, GL_FLOAT, 0, 0, offsets[4]);
|
glVertexAttribPointer(loc2, 3, GL_FLOAT, 0, 0, offsets[4]);
|
||||||
|
locs << loc << loc2;
|
||||||
} else {
|
} else {
|
||||||
glDisableVertexAttribArray(loc);
|
glDisableVertexAttribArray(loc);
|
||||||
glDisableVertexAttribArray(loc2);
|
glDisableVertexAttribArray(loc2);
|
||||||
@@ -200,6 +206,8 @@ void GLVBO::draw(GLenum type, QGLShaderProgram * prog, bool simplest) {
|
|||||||
glDrawArrays(type, 0, vert_count);
|
glDrawArrays(type, 0, vert_count);
|
||||||
//qDebug() << "draw" << vert_count << buffer_ << "done";
|
//qDebug() << "draw" << vert_count << buffer_ << "done";
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||||
|
foreach (int l, locs)
|
||||||
|
glDisableVertexAttribArray(l);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ private:
|
|||||||
void calculateBinormals();
|
void calculateBinormals();
|
||||||
|
|
||||||
QVector<GLfloat> vertices_, normals_, texcoords_, colors_, tangents_, bitangents_;
|
QVector<GLfloat> vertices_, normals_, texcoords_, colors_, tangents_, bitangents_;
|
||||||
|
QVector<int> locs;
|
||||||
GLenum usage;
|
GLenum usage;
|
||||||
GLuint buffer_, va_;
|
GLuint buffer_, va_;
|
||||||
int vert_count;
|
int vert_count;
|
||||||
|
|||||||
@@ -245,9 +245,8 @@ GLObjectBase * loadFrom3DSFile(const QString & filepath, double scale) {
|
|||||||
globject_cast<Light * >(co)->direction = (pos.toQVector3D() - co->pos()).normalized();
|
globject_cast<Light * >(co)->direction = (pos.toQVector3D() - co->pos()).normalized();
|
||||||
stream.readRawData((char * )&fl1, sizeof(float));
|
stream.readRawData((char * )&fl1, sizeof(float));
|
||||||
stream.readRawData((char * )&fl, sizeof(float));
|
stream.readRawData((char * )&fl, sizeof(float));
|
||||||
fl1 /= 2.f; fl /= 2.f;
|
globject_cast<Light * >(co)->angle_start = fl1;
|
||||||
globject_cast<Light * >(co)->angle_spread = fl;
|
globject_cast<Light * >(co)->angle_end = fl;
|
||||||
globject_cast<Light * >(co)->angle_decay_exp = (fl - fl1) / fl * 16.;
|
|
||||||
//qDebug() << "spotlight" << globject_cast<Light * >(co)->direction << globject_cast<Light * >(co)->angle_spread;
|
//qDebug() << "spotlight" << globject_cast<Light * >(co)->direction << globject_cast<Light * >(co)->angle_spread;
|
||||||
break;
|
break;
|
||||||
case LOADER_3DS_CHUNK_LIGHT_OFF:
|
case LOADER_3DS_CHUNK_LIGHT_OFF:
|
||||||
|
|||||||
@@ -371,6 +371,10 @@ GLObjectBase * loadFromDAEFile(const QString & filepath, double scale) {
|
|||||||
sv = dl.firstChildElement("linear_attenuation").firstChild().nodeValue(); if (!sv.isEmpty()) lo->decay_linear = sv.toDouble();
|
sv = dl.firstChildElement("linear_attenuation").firstChild().nodeValue(); if (!sv.isEmpty()) lo->decay_linear = sv.toDouble();
|
||||||
sv = dl.firstChildElement("quadratic_attenuation").firstChild().nodeValue(); if (!sv.isEmpty()) lo->decay_quadratic = sv.toDouble();
|
sv = dl.firstChildElement("quadratic_attenuation").firstChild().nodeValue(); if (!sv.isEmpty()) lo->decay_quadratic = sv.toDouble();
|
||||||
///lo->setTransform(matrices.value(name));
|
///lo->setTransform(matrices.value(name));
|
||||||
|
if (lo->light_type == Light::Cone) {
|
||||||
|
ml = dn.elementsByTagName("decay_falloff"); if (!ml.isEmpty()) lo->angle_end = ml.at(0).firstChild().nodeValue().toDouble();
|
||||||
|
ml = dn.elementsByTagName("hotspot_beam"); if (!ml.isEmpty()) lo->angle_start = ml.at(0).firstChild().nodeValue().toDouble();
|
||||||
|
}
|
||||||
QVector<GLObjectBase*> ol;
|
QVector<GLObjectBase*> ol;
|
||||||
ol << lo;
|
ol << lo;
|
||||||
objects[gid] = ol;
|
objects[gid] = ol;
|
||||||
|
|||||||
@@ -32,8 +32,8 @@ MainWindow::MainWindow(QWidget * parent): QMainWindow(parent), Ui::MainWindow()
|
|||||||
sel_obj = 0;
|
sel_obj = 0;
|
||||||
//spinSliderShine->setDecimals(2);
|
//spinSliderShine->setDecimals(2);
|
||||||
view->setFrameShape(QFrame::NoFrame);
|
view->setFrameShape(QFrame::NoFrame);
|
||||||
//view->setRenderer(new RendererDeferredShading(view));
|
view->setRenderer(new RendererDeferredShading(view));
|
||||||
view->setRenderer(new RendererSimple(view));
|
//view->setRenderer(new RendererSimple(view));
|
||||||
view->setMouseRotateEnabled(true);
|
view->setMouseRotateEnabled(true);
|
||||||
view->setMouseSelectionEnabled(true);
|
view->setMouseSelectionEnabled(true);
|
||||||
view->setSelectionHaloEnabled(true);
|
view->setSelectionHaloEnabled(true);
|
||||||
@@ -76,8 +76,8 @@ MainWindow::MainWindow(QWidget * parent): QMainWindow(parent), Ui::MainWindow()
|
|||||||
//obj = new GLPrimitiveEllipsoid(100, 100, 100, 100, 100);//GLPrimitiveCube();
|
//obj = new GLPrimitiveEllipsoid(100, 100, 100, 100, 100);//GLPrimitiveCube();
|
||||||
for (int i = 0; i < obj->childCount(); ++i)
|
for (int i = 0; i < obj->childCount(); ++i)
|
||||||
if (obj->child(i)->type() == GLObjectBase::Light) {
|
if (obj->child(i)->type() == GLObjectBase::Light) {
|
||||||
((Light*)obj->child(i))->intensity = 1.5;
|
//((Light*)obj->child(i))->intensity = 1.5;
|
||||||
((Light*)obj->child(i))->decay_linear = .5;
|
//((Light*)obj->child(i))->decay_linear = .5;
|
||||||
}
|
}
|
||||||
view->addObject(obj);
|
view->addObject(obj);
|
||||||
//obj->child("Box001")->addChild(&(view->camera()));
|
//obj->child("Box001")->addChild(&(view->camera()));
|
||||||
@@ -100,13 +100,13 @@ MainWindow::MainWindow(QWidget * parent): QMainWindow(parent), Ui::MainWindow()
|
|||||||
|
|
||||||
view->camera().setPos(QVector3D(10, -20, 20));
|
view->camera().setPos(QVector3D(10, -20, 20));
|
||||||
view->camera().setAim(QVector3D());
|
view->camera().setAim(QVector3D());
|
||||||
view->camera().flyToDistance(100);
|
view->camera().flyToDistance(1000);
|
||||||
//view->camera().setMode(Camera::AimMatrix);
|
//view->camera().setMode(Camera::AimMatrix);
|
||||||
Light * l = new Light(view->camera().pos());
|
Light * l = new Light(view->camera().pos());
|
||||||
l->intensity = 0.5;
|
l->intensity = 0.5;
|
||||||
l->decay_linear = 0.2;
|
l->decay_linear = 0.2;
|
||||||
l->setName("camera");
|
l->setName("camera");
|
||||||
view->addObject(l);
|
//view->addObject(l);
|
||||||
view->start(-1);
|
view->start(-1);
|
||||||
//view->light(0)->light_type = Light::Omni;
|
//view->light(0)->light_type = Light::Omni;
|
||||||
//obj = loadFrom3DSFile("34.3DS", 0.03);
|
//obj = loadFrom3DSFile("34.3DS", 0.03);
|
||||||
|
|||||||
@@ -55,8 +55,8 @@ QGLView::QGLView(QWidget * parent): QGraphicsView(parent), fbo_selection(3) {
|
|||||||
//lmode = Simple;
|
//lmode = Simple;
|
||||||
shader_select = shader_halo = 0;
|
shader_select = shader_halo = 0;
|
||||||
cur_luminance = 1.;
|
cur_luminance = 1.;
|
||||||
accom_time = 32.;
|
accom_time = 16.;
|
||||||
accom_max_speed = 0.1;
|
accom_max_speed = 0.2;
|
||||||
mouse_first = mouseSelect_ = accomodation_ = hoverHalo_ = selectionHalo_ = true;
|
mouse_first = mouseSelect_ = accomodation_ = hoverHalo_ = selectionHalo_ = true;
|
||||||
fogEnabled_ = is_init = grabMouse_ = mouseRotate_ = mouseThis_ = shaders_bind = shadows_ = shadows_soft = dynamic_reflections = hdr_ = bloom_ = msaa_ = fxaa_ = changed_ = false;
|
fogEnabled_ = is_init = grabMouse_ = mouseRotate_ = mouseThis_ = shaders_bind = shadows_ = shadows_soft = dynamic_reflections = hdr_ = bloom_ = msaa_ = fxaa_ = changed_ = false;
|
||||||
rmode = GLObjectBase::Fill;
|
rmode = GLObjectBase::Fill;
|
||||||
@@ -304,6 +304,10 @@ void QGLView::paintGL() {
|
|||||||
qDebug() << QRect(downPos, lastPos).normalized();
|
qDebug() << QRect(downPos, lastPos).normalized();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
glReleaseShaders();
|
||||||
|
glResetAllTransforms();
|
||||||
|
glReleaseFramebuffer();
|
||||||
|
|
||||||
emit glPainting();
|
emit glPainting();
|
||||||
|
|
||||||
/*releaseShaders();
|
/*releaseShaders();
|
||||||
|
|||||||
@@ -17,14 +17,40 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "renderer_deferred_shading.h"
|
#include "renderer_deferred_shading.h"
|
||||||
|
#include <QBoxLayout>
|
||||||
|
|
||||||
|
|
||||||
RendererDeferredShading::RendererDeferredShading(QGLView * view_): GLRendererBase(view_), fbo_g(4, true, GL_RGBA16F), fbo_out(2, GL_RGBA16F) {
|
RendererDeferredShading::RendererDeferredShading(QGLView * view_): GLRendererBase(view_),
|
||||||
shader_fxaa = shader_ds_0 = shader_ds_1 = 0;
|
fbo_g(4, true, GL_RGBA16F), fbo_out(2, false, GL_RGB16F), fbo_hsmall(1, false, GL_RGB16F) {
|
||||||
|
shader_fxaa = shader_ds_0 = shader_ds_1 = shader_hdr = shader_small = 0;
|
||||||
|
lights_per_pass = 2;
|
||||||
|
exposure_ = 1.;
|
||||||
|
df = new QWidget();
|
||||||
|
df->setLayout(new QBoxLayout(QBoxLayout::TopToBottom));
|
||||||
|
label_exp = new QLabel();
|
||||||
|
label_exp_step = new QLabel();
|
||||||
|
df->layout()->addWidget(label_exp);
|
||||||
|
df->layout()->addWidget(label_exp_step);
|
||||||
|
QPalette pal(df->palette());
|
||||||
|
pal.setBrush(QPalette::Window, QColor(255, 255, 255, 192));
|
||||||
|
df->setPalette(pal);
|
||||||
|
if (view_)
|
||||||
|
view_->addObject(df);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
RendererDeferredShading::~RendererDeferredShading() {
|
||||||
|
if (shader_fxaa != 0) delete shader_fxaa;
|
||||||
|
if (shader_ds_0 != 0) delete shader_ds_0;
|
||||||
|
if (shader_ds_1 != 0) delete shader_ds_1;
|
||||||
|
if (shader_hdr != 0) delete shader_hdr;
|
||||||
|
if (shader_small != 0) delete shader_small;
|
||||||
|
delete df;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void RendererDeferredShading::renderScene() {
|
void RendererDeferredShading::renderScene() {
|
||||||
|
//qDebug() << lights_per_pass;
|
||||||
QMatrix4x4 mproji = rp.proj_matrix_i;
|
QMatrix4x4 mproji = rp.proj_matrix_i;
|
||||||
QMatrix4x4 mview = rp.view_matrix;
|
QMatrix4x4 mview = rp.view_matrix;
|
||||||
corner_dirs[0] = (QVector4D(-1, -1, 1, 1) * rp.viewproj_matrix).normalized();
|
corner_dirs[0] = (QVector4D(-1, -1, 1, 1) * rp.viewproj_matrix).normalized();
|
||||||
@@ -48,7 +74,7 @@ void RendererDeferredShading::renderScene() {
|
|||||||
glActiveTextureChannel(0);
|
glActiveTextureChannel(0);
|
||||||
}
|
}
|
||||||
glClearFramebuffer(QColor(0, 0, 0, 0));
|
glClearFramebuffer(QColor(0, 0, 0, 0));
|
||||||
//glEnable(GL_TEXTURE_2D);
|
glDisable(GL_RESCALE_NORMAL);
|
||||||
glEnableDepth();
|
glEnableDepth();
|
||||||
shader_ds_0->bind();
|
shader_ds_0->bind();
|
||||||
rp.setUniform(shader_ds_0);
|
rp.setUniform(shader_ds_0);
|
||||||
@@ -61,7 +87,7 @@ void RendererDeferredShading::renderScene() {
|
|||||||
shader_ds_0->setUniformValue("dt", QVector2D(1. / view.viewport()->width(), 1. / view.viewport()->height()));
|
shader_ds_0->setUniformValue("dt", QVector2D(1. / view.viewport()->width(), 1. / view.viewport()->height()));
|
||||||
renderObjects(GLObjectBase::Solid, 0, shader_ds_0, true, false, false);
|
renderObjects(GLObjectBase::Solid, 0, shader_ds_0, true, false, false);
|
||||||
//glReleaseShaders();
|
//glReleaseShaders();
|
||||||
//fbo.release();
|
fbo_g.release();
|
||||||
|
|
||||||
glResetAllTransforms();
|
glResetAllTransforms();
|
||||||
rp.prepare();
|
rp.prepare();
|
||||||
@@ -89,28 +115,72 @@ void RendererDeferredShading::renderScene() {
|
|||||||
glClearFramebuffer(Qt::black, false);
|
glClearFramebuffer(Qt::black, false);
|
||||||
//QVector<QVector4D> lpos;
|
//QVector<QVector4D> lpos;
|
||||||
//qDebug() << view_matrix;
|
//qDebug() << view_matrix;
|
||||||
int passes = (view.lightsCount() - 1) / 16 + 1;
|
int passes = (view.lightsCount() - 1) / lights_per_pass + 1;
|
||||||
if (passes < 1) passes = 1;
|
if (passes < 1) passes = 1;
|
||||||
shader_ds_1->setUniformValue("t_pp", 5);
|
shader_ds_1->setUniformValue("t_pp", 5);
|
||||||
//qDebug() << "render in" << passes << "passes";
|
//qDebug() << "render in" << passes << "passes (" << lights_per_pass << ")";
|
||||||
|
int wi, ri;
|
||||||
for (int l = 0; l < passes; ++l) {
|
for (int l = 0; l < passes; ++l) {
|
||||||
int wi = 1 - l % 2, ri = l % 2;
|
wi = 1 - l % 2;
|
||||||
|
ri = l % 2;
|
||||||
//qDebug() << " pass" << l << "read from" << ri << "write to" << wi;
|
//qDebug() << " pass" << l << "read from" << ri << "write to" << wi;
|
||||||
glActiveTextureChannel(5);
|
glActiveTextureChannel(5);
|
||||||
glBindTexture(GL_TEXTURE_2D, fbo_out.colorTexture(ri));
|
glBindTexture(GL_TEXTURE_2D, fbo_out.colorTexture(ri));
|
||||||
fbo_out.setWriteBuffer(wi);
|
fbo_out.setWriteBuffer(wi);
|
||||||
setupDSLights(l, 16, mview);
|
setupDSLights(l, mview);
|
||||||
//shader_ds_1->setUniformValue("lightsCount", cplc);
|
//shader_ds_1->setUniformValue("lightsCount", cplc);
|
||||||
glDrawQuad(shader_ds_1);
|
glDrawQuad(shader_ds_1);
|
||||||
//renderObjects(GLObjectBase::Solid, l, 0, true, true, view.isFogEnabled());
|
//renderObjects(GLObjectBase::Solid, l, 0, true, true, view.isFogEnabled());
|
||||||
//renderObjects(GLObjectBase::Transparent, l, 0, true, true, view.isFogEnabled());
|
//renderObjects(GLObjectBase::Transparent, l, 0, true, true, view.isFogEnabled());
|
||||||
glFinish();
|
//glFinish();
|
||||||
//break;
|
//break;
|
||||||
}
|
}
|
||||||
fbo_out.release();
|
fbo_out.release();
|
||||||
glReleaseShaders();
|
wi = 1 - passes % 2;
|
||||||
|
ri = passes % 2;
|
||||||
glActiveTextureChannel(0);
|
glActiveTextureChannel(0);
|
||||||
glBindTexture(GL_TEXTURE_2D, fbo_out.colorTexture(passes % 2));
|
glBindTexture(GL_TEXTURE_2D, fbo_out.colorTexture(ri));
|
||||||
|
|
||||||
|
fbo_hsmall.bind();
|
||||||
|
fbo_hsmall.setWriteBuffer(0);
|
||||||
|
shader_small->bind();
|
||||||
|
shader_small->setUniformValue("qgl_ModelViewProjectionMatrix", QMatrix4x4());
|
||||||
|
shader_small->setUniformValue("t0", 0);
|
||||||
|
glDrawQuad(shader_small);
|
||||||
|
hcontent.resize(fbo_hsmall.width() * fbo_hsmall.height());
|
||||||
|
glReadPixels(0, 0, fbo_hsmall.width(), fbo_hsmall.height(), GL_RGB, GL_FLOAT, hcontent.data());
|
||||||
|
GLfloat max[3] = {0.,0.,0.};//min[3] = {10000.,10000.,10000.}, ;
|
||||||
|
for (int i = 0; i < hcontent.size(); ++i) {
|
||||||
|
//if (min[0] > hcontent[i].x) min[0] = hcontent[i].x;
|
||||||
|
if (max[0] < hcontent[i].x) max[0] = hcontent[i].x;
|
||||||
|
//if (min[1] > hcontent[i].y) min[1] = hcontent[i].y;
|
||||||
|
if (max[1] < hcontent[i].y) max[1] = hcontent[i].y;
|
||||||
|
//if (min[2] > hcontent[i].z) min[2] = hcontent[i].z;
|
||||||
|
if (max[2] < hcontent[i].z) max[2] = hcontent[i].z;
|
||||||
|
}
|
||||||
|
GLfloat mluma = (0.299 * max[0]) + (0.587 * max[1]) + (0.114 * max[2]);
|
||||||
|
double nexp = mluma / 16., dexp = nexp - exposure_, mestep = exposure_ * view.accomodationMaxSpeed();
|
||||||
|
dexp /= view.accomodationTime();
|
||||||
|
if (dexp > 0. && dexp > mestep/4) dexp = mestep/4;
|
||||||
|
if (dexp < 0. && dexp < -mestep) dexp = -mestep;
|
||||||
|
exposure_ += dexp;
|
||||||
|
label_exp->setText(QString("exposure: %1").arg(exposure_));
|
||||||
|
label_exp_step->setText(QString("d_exposure: %1").arg(dexp));
|
||||||
|
//qDebug() << min[0] << max[0] << min[1] << max[1] << min[2] << max[2];
|
||||||
|
fbo_hsmall.release();
|
||||||
|
|
||||||
|
//glBindTexture(GL_TEXTURE_2D, fbo_out.colorTexture(ri));
|
||||||
|
fbo_out.bind();
|
||||||
|
fbo_out.setWriteBuffer(wi);
|
||||||
|
shader_hdr->bind();
|
||||||
|
shader_hdr->setUniformValue("qgl_ModelViewProjectionMatrix", QMatrix4x4());
|
||||||
|
shader_hdr->setUniformValue("t0", 0);
|
||||||
|
shader_hdr->setUniformValue("exposure", GLfloat(1./exposure_));
|
||||||
|
glDrawQuad(shader_hdr);
|
||||||
|
fbo_out.release();
|
||||||
|
|
||||||
|
glBindTexture(GL_TEXTURE_2D, fbo_out.colorTexture(wi));
|
||||||
|
glReleaseShaders();
|
||||||
if (view.isFXAAEnabled()) {
|
if (view.isFXAAEnabled()) {
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
@@ -127,14 +197,16 @@ void RendererDeferredShading::renderScene() {
|
|||||||
|
|
||||||
|
|
||||||
void RendererDeferredShading::init(int width, int height) {
|
void RendererDeferredShading::init(int width, int height) {
|
||||||
fbo_g.resize(width, height);
|
resize(width, height);
|
||||||
fbo_out.resize(width, height);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void RendererDeferredShading::resize(int width, int height) {
|
void RendererDeferredShading::resize(int width, int height) {
|
||||||
fbo_g.resize(width, height);
|
fbo_g.resize(width, height);
|
||||||
fbo_out.resize(width, height);
|
fbo_out.resize(width, height);
|
||||||
|
fbo_hsmall.resize(width / 16, height / 16);
|
||||||
|
view.setSceneRect(QRect(0, 0, width, height)); /// WARNING
|
||||||
|
//df->move(-width / 2, -height / 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -142,10 +214,13 @@ void RendererDeferredShading::reloadShaders() {
|
|||||||
if (shader_fxaa == 0) shader_fxaa = new QGLShaderProgram(view.context());
|
if (shader_fxaa == 0) shader_fxaa = new QGLShaderProgram(view.context());
|
||||||
if (shader_ds_0 == 0) shader_ds_0 = new QGLShaderProgram(view.context());
|
if (shader_ds_0 == 0) shader_ds_0 = new QGLShaderProgram(view.context());
|
||||||
if (shader_ds_1 == 0) shader_ds_1 = new QGLShaderProgram(view.context());
|
if (shader_ds_1 == 0) shader_ds_1 = new QGLShaderProgram(view.context());
|
||||||
//if (shader_ds_0 == 0) shader_ds_0 = new QGLShaderProgram(view.context());
|
if (shader_hdr == 0) shader_hdr = new QGLShaderProgram(view.context());
|
||||||
|
if (shader_small == 0) shader_small = new QGLShaderProgram(view.context());
|
||||||
loadShaders(shader_fxaa, "FXAA", "shaders");
|
loadShaders(shader_fxaa, "FXAA", "shaders");
|
||||||
loadShaders(shader_ds_0, "dsl_pass_0", "shaders");
|
loadShaders(shader_ds_0, "dsl_pass_0", "shaders");
|
||||||
loadShaders(shader_ds_1, "dsl_pass_1", "shaders");
|
loadShaders(shader_ds_1, "dsl_pass_1", "shaders");
|
||||||
|
loadShaders(shader_hdr, "hdr", "shaders");
|
||||||
|
loadShaders(shader_small, "downscale", "shaders");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -162,7 +237,7 @@ void RendererDeferredShading::setupShadersTextures(GLObjectBase & object, GLRend
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void RendererDeferredShading::setupDSLights(int pass, int lights_per_pass, const QMatrix4x4 & view_matrix) {
|
void RendererDeferredShading::setupDSLights(int pass, const QMatrix4x4 & view_matrix) {
|
||||||
int light_start, light_end, lmax;
|
int light_start, light_end, lmax;
|
||||||
light_start = pass * lights_per_pass;
|
light_start = pass * lights_per_pass;
|
||||||
light_end = qMin<int>((pass + 1) * lights_per_pass, view.lights().size());
|
light_end = qMin<int>((pass + 1) * lights_per_pass, view.lights().size());
|
||||||
|
|||||||
@@ -20,12 +20,13 @@
|
|||||||
#define RENDERER_DEFERRED_SHADING_H
|
#define RENDERER_DEFERRED_SHADING_H
|
||||||
|
|
||||||
#include "qglview.h"
|
#include "qglview.h"
|
||||||
|
#include <QLabel>
|
||||||
|
|
||||||
class RendererDeferredShading: public GLRendererBase
|
class RendererDeferredShading: public GLRendererBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
RendererDeferredShading(QGLView * view);
|
RendererDeferredShading(QGLView * view);
|
||||||
virtual ~RendererDeferredShading() {if (shader_fxaa != 0) delete shader_fxaa;}
|
virtual ~RendererDeferredShading();
|
||||||
|
|
||||||
virtual void renderScene();
|
virtual void renderScene();
|
||||||
|
|
||||||
@@ -35,19 +36,24 @@ protected:
|
|||||||
void reloadShaders();
|
void reloadShaders();
|
||||||
void setupShadersTextures(GLObjectBase & object, RenderingParameters & rp);
|
void setupShadersTextures(GLObjectBase & object, RenderingParameters & rp);
|
||||||
void setupShadersLights(int lights_count) {cplc = lights_count;}
|
void setupShadersLights(int lights_count) {cplc = lights_count;}
|
||||||
void setupDSLights(int pass, int lights_per_pass, const QMatrix4x4 & view_matrix);
|
void setupDSLights(int pass, const QMatrix4x4 & view_matrix);
|
||||||
void setupAmbientLight(const QColor & a, bool first_pass);
|
void setupAmbientLight(const QColor & a, bool first_pass);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int cplc;
|
int cplc, BUG[8], lights_per_pass;
|
||||||
GLFramebuffer fbo_g, fbo_out;
|
double exposure_;
|
||||||
QGLShaderProgram * shader_fxaa, * shader_ds_0, * shader_ds_1;
|
GLFramebuffer fbo_g, fbo_out, fbo_hsmall;
|
||||||
|
QGLShaderProgram * shader_fxaa, * shader_ds_0, * shader_ds_1, * shader_hdr, * shader_small;
|
||||||
|
|
||||||
QMatrix4x4 pm, mvm, mvpm, pim, mvim, mvpim;
|
QMatrix4x4 pm, mvm, mvpm, pim, mvim, mvpim;
|
||||||
QMatrix3x3 nm;
|
QMatrix3x3 nm;
|
||||||
QVector4D corner_dirs[4];
|
QVector4D corner_dirs[4];
|
||||||
|
QVector<Vector3d> hcontent;
|
||||||
Light amb_light;
|
Light amb_light;
|
||||||
|
|
||||||
|
QWidget * df;
|
||||||
|
QLabel * label_exp, * label_exp_step;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // RENDERER_DEFERRED_SHADING_H
|
#endif // RENDERER_DEFERRED_SHADING_H
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ void RendererSimple::renderScene() {
|
|||||||
fbo.setWriteBuffer(0);
|
fbo.setWriteBuffer(0);
|
||||||
glClearFramebuffer();
|
glClearFramebuffer();
|
||||||
}
|
}
|
||||||
|
glEnable(GL_RESCALE_NORMAL);
|
||||||
for (int l = 0; l < passes; ++l) {
|
for (int l = 0; l < passes; ++l) {
|
||||||
if (passes > 1) fbo.setWriteBuffer(1);
|
if (passes > 1) fbo.setWriteBuffer(1);
|
||||||
if (l == 0) {
|
if (l == 0) {
|
||||||
|
|||||||
7
qglview/shaders/downscale.frag
Normal file
7
qglview/shaders/downscale.frag
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#version 150
|
||||||
|
|
||||||
|
uniform sampler2D t0;
|
||||||
|
|
||||||
|
void main(void) {
|
||||||
|
qgl_FragData[0].rgb = textureLod(t0, qgl_FragTexture.xy, 3).rgb;
|
||||||
|
}
|
||||||
6
qglview/shaders/downscale.vert
Normal file
6
qglview/shaders/downscale.vert
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
#version 150
|
||||||
|
|
||||||
|
void main(void) {
|
||||||
|
qgl_FragTexture = qgl_Texture;
|
||||||
|
gl_Position = qgl_ftransform();
|
||||||
|
}
|
||||||
@@ -15,11 +15,11 @@ void main(void) {
|
|||||||
float z = pos.w;//((z_near / (z_near-z_far)) * z_far) / (pos.w - (z_far / (z_far-z_near)));
|
float z = pos.w;//((z_near / (z_near-z_far)) * z_far) / (pos.w - (z_far / (z_far-z_near)));
|
||||||
vec4 dc = qgl_FragColor;
|
vec4 dc = qgl_FragColor;
|
||||||
vec2 tc = qgl_FragTexture.xy;
|
vec2 tc = qgl_FragTexture.xy;
|
||||||
float hei = dot(texture2D(qgl_Material.map_relief.map, tc).rgb, luma) * qgl_Material.map_relief.amount + qgl_Material.map_relief.offset;
|
float hei = dot(texture(qgl_Material.map_relief.map, tc).rgb, luma) * qgl_Material.map_relief.amount + qgl_Material.map_relief.offset;
|
||||||
//if (acc_fog) dc.xyz = mix(dc.rgb, gl_Fog.color.rgb, fogCoord);
|
//if (acc_fog) dc.xyz = mix(dc.rgb, gl_Fog.color.rgb, fogCoord);
|
||||||
|
|
||||||
vec3 n, dn;
|
vec3 n, dn;
|
||||||
dn = (texture2D(qgl_Material.map_normal.map, tc).rgb - vec3(0.5, 0.5, 1.)) * qgl_Material.map_normal.amount + qgl_Material.map_normal.offset;
|
dn = (texture(qgl_Material.map_normal.map, tc).rgb - vec3(0.5, 0.5, 1.)) * qgl_Material.map_normal.amount + qgl_Material.map_normal.offset;
|
||||||
//float tx = dn.x;
|
//float tx = dn.x;
|
||||||
dn.y = -dn.y;
|
dn.y = -dn.y;
|
||||||
//dn.y = tx;
|
//dn.y = tx;
|
||||||
@@ -34,12 +34,12 @@ void main(void) {
|
|||||||
dpm = dpm * gl_ModelViewProjectionMatrixInverse;
|
dpm = dpm * gl_ModelViewProjectionMatrixInverse;
|
||||||
dpm += */
|
dpm += */
|
||||||
//tc += 1+et.xy * hei/10;// / et.z;
|
//tc += 1+et.xy * hei/10;// / et.z;
|
||||||
dc *= texture2D(qgl_Material.map_diffuse.map, tc) * qgl_Material.map_diffuse.amount + qgl_Material.map_diffuse.offset;
|
dc *= texture(qgl_Material.map_diffuse.map, tc) * qgl_Material.map_diffuse.amount + qgl_Material.map_diffuse.offset;
|
||||||
|
|
||||||
vec4 spec = texture2D(qgl_Material.map_specular.map, tc) * qgl_Material.map_specular.amount + qgl_Material.map_specular.offset;
|
vec4 spec = texture(qgl_Material.map_specular.map, tc) * qgl_Material.map_specular.amount + qgl_Material.map_specular.offset;
|
||||||
spec *= qgl_Material.color_specular;
|
spec *= qgl_Material.color_specular;
|
||||||
vec4 specularity = texture2D(qgl_Material.map_specularity.map, tc) * qgl_Material.map_specularity.amount + qgl_Material.map_specularity.offset;
|
vec4 specularity = texture(qgl_Material.map_specularity.map, tc) * qgl_Material.map_specularity.amount + qgl_Material.map_specularity.offset;
|
||||||
vec4 self = texture2D(qgl_Material.map_self_illumination.map, tc) * qgl_Material.map_self_illumination.amount + qgl_Material.map_self_illumination.offset;
|
vec4 self = texture(qgl_Material.map_self_illumination.map, tc) * qgl_Material.map_self_illumination.amount + qgl_Material.map_self_illumination.offset;
|
||||||
self *= qgl_Material.color_self_illumination;
|
self *= qgl_Material.color_self_illumination;
|
||||||
|
|
||||||
qgl_FragData[0] = vec4(dc.rgb, z);
|
qgl_FragData[0] = vec4(dc.rgb, z);
|
||||||
|
|||||||
@@ -25,5 +25,6 @@ void main(void) {
|
|||||||
//tp /= tp.w;
|
//tp /= tp.w;
|
||||||
src_normal = normalize(vec3(pos.xy * dt * 2., 0));
|
src_normal = normalize(vec3(pos.xy * dt * 2., 0));
|
||||||
pos.w = tp.w;
|
pos.w = tp.w;
|
||||||
|
//pos *= pos.w;
|
||||||
gl_Position = tp;//ftransform();
|
gl_Position = tp;//ftransform();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,11 +30,13 @@ void calcLight(in int index, in vec3 n, in vec3 v, in vec4 v2) {
|
|||||||
NdotH = max(dot(n, halfV), 0.);
|
NdotH = max(dot(n, halfV), 0.);
|
||||||
spot = step(0., NdotL) * qgl_Light[index].intensity;
|
spot = step(0., NdotL) * qgl_Light[index].intensity;
|
||||||
if (NdotL > 0.) {
|
if (NdotL > 0.) {
|
||||||
/*if (gl_LightSource[index].spotCutoff < 180.) {
|
if (qgl_Light[index].endAngle <= 90.) {
|
||||||
spot = max(dot(-ldir, gl_LightSource[index].spotDirection.xyz), 0.);
|
float scos = max(dot(-ldir, qgl_Light[index].direction.xyz), 0.);
|
||||||
spot *= step(gl_LightSource[index].spotCosCutoff, spot);
|
spot *= scos * step(qgl_Light[index].endAngleCos, scos);
|
||||||
spot = pow(spot, (gl_LightSource[index].spotExponent + 0.001));
|
//spot = clamp(scos / (-qgl_Light[index].endAngleCos + qgl_Light[index].startAngleCos + 0.0001),0,1);
|
||||||
}*/
|
spot *= smoothstep(qgl_Light[index].endAngleCos, qgl_Light[index].startAngleCos, scos);
|
||||||
|
//spot = pow(spot, (qgl_Light[index].spotExponent + 0.001));
|
||||||
|
}
|
||||||
spot /= (qgl_Light[index].constantAttenuation + ldist * (qgl_Light[index].linearAttenuation + ldist * qgl_Light[index].quadraticAttenuation));
|
spot /= (qgl_Light[index].constantAttenuation + ldist * (qgl_Light[index].linearAttenuation + ldist * qgl_Light[index].quadraticAttenuation));
|
||||||
///li += spot * gl_LightSource[index].diffuse.rgb * light_diffuse(0, ldir, n);
|
///li += spot * gl_LightSource[index].diffuse.rgb * light_diffuse(0, ldir, n);
|
||||||
//si += spot * qgl_Light[index].color.rgb * sh_mul * light_specular(0, ldir, n, halfV, v, sh_pow);
|
//si += spot * qgl_Light[index].color.rgb * sh_mul * light_specular(0, ldir, n, halfV, v, sh_pow);
|
||||||
@@ -72,6 +74,7 @@ void main(void) {
|
|||||||
pos.xy *= v3.w;
|
pos.xy *= v3.w;
|
||||||
pos.z = posz;
|
pos.z = posz;
|
||||||
pos.xyz += n * height;
|
pos.xyz += n * height;
|
||||||
|
//pos.xyz = v3.xyz;
|
||||||
//pos = v3;
|
//pos = v3;
|
||||||
//pos = vec4(sp, 0, 1.) * mat_proji;
|
//pos = vec4(sp, 0, 1.) * mat_proji;
|
||||||
//pos *= v0.w;
|
//pos *= v0.w;
|
||||||
@@ -79,37 +82,15 @@ void main(void) {
|
|||||||
//pos.xy *= 10.;
|
//pos.xy *= 10.;
|
||||||
//pos.z = v0.w;
|
//pos.z = v0.w;
|
||||||
vec3 v = normalize(-pos.xyz);
|
vec3 v = normalize(-pos.xyz);
|
||||||
|
|
||||||
sh_pow = 1. / max((1. - v1.w), 0.0001);
|
sh_pow = 1. / max((1. - v1.w), 0.0001);
|
||||||
sh_mul = max(1. - v1.w, 0.0001);
|
sh_mul = max(1. - v1.w, 0.0001);
|
||||||
//for (int i = 0; i < 16; ++i)
|
for (int i = 0; i < 16; ++i)
|
||||||
calcLight(7, n, v, v2);
|
calcLight(i, n, v, v2);
|
||||||
/*if (lightsCount > 0) {
|
|
||||||
calcLight(0, n, v, v2);
|
qgl_FragData[0].rgb = li * dc + si * v2.rgb + v3.rgb + texture(t_pp, tc).rgb;
|
||||||
if (lightsCount > 1) {
|
|
||||||
calcLight(1, n, v, v2);
|
|
||||||
if (lightsCount > 2) {
|
|
||||||
calcLight(2, n, v, v2);
|
|
||||||
if (lightsCount > 3) {
|
|
||||||
calcLight(3, n, v, v2);
|
|
||||||
if (lightsCount > 4) {
|
|
||||||
calcLight(4, n, v, v2);
|
|
||||||
if (lightsCount > 5) {
|
|
||||||
calcLight(5, n, v, v2);
|
|
||||||
if (lightsCount > 6) {
|
|
||||||
calcLight(6, n, v, v2);
|
|
||||||
if (lightsCount > 7) {
|
|
||||||
calcLight(7, n, v, v2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
qgl_FragData[0].rgb = li * dc + si * v2.rgb + v3.rgb + texture2D(t_pp, tc).rgb;
|
|
||||||
//qgl_FragData[0].rgb = vec3(abs(lpos.xyz - pos.xyz)/10);
|
//qgl_FragData[0].rgb = vec3(abs(lpos.xyz - pos.xyz)/10);
|
||||||
//qgl_FragData[0].rgb = texture2D(t_pp, tc).rgb;
|
//qgl_FragData[0].rgb = si.rgb;
|
||||||
//qgl_FragData[0].rgb = vec3(pow(NdotH,100)*2);
|
//qgl_FragData[0].rgb = (v0.rgb)/2;
|
||||||
//qgl_FragData[0].a = 0.;
|
//qgl_FragData[0].a = 0.;
|
||||||
}
|
}
|
||||||
|
|||||||
27
qglview/shaders/hdr.frag
Normal file
27
qglview/shaders/hdr.frag
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
#version 150
|
||||||
|
|
||||||
|
uniform sampler2D t0;
|
||||||
|
uniform float exposure;
|
||||||
|
|
||||||
|
float tA = 0.15;
|
||||||
|
float tB = 0.50;
|
||||||
|
float tC = 0.10;
|
||||||
|
float tD = 0.20;
|
||||||
|
float tE = 0.02;
|
||||||
|
float tF = 0.30;
|
||||||
|
float tW = 11.2;
|
||||||
|
|
||||||
|
vec3 Uncharted2Tonemap(vec3 x) {
|
||||||
|
return ((x*(tA*x+tC*tB)+tD*tE)/(x*(tA*x+tB)+tD*tF))-tE/tF;
|
||||||
|
}
|
||||||
|
|
||||||
|
void main(void) {
|
||||||
|
vec3 inColor = texture(t0, qgl_FragTexture.xy).rgb;
|
||||||
|
inColor *= exposure;
|
||||||
|
float ExposureBias = 1;
|
||||||
|
vec3 curr = Uncharted2Tonemap(ExposureBias*inColor);
|
||||||
|
vec3 whiteScale = 1 / Uncharted2Tonemap(vec3(tW));
|
||||||
|
vec3 color = curr * whiteScale;
|
||||||
|
vec3 retColor = pow(color, vec3(1 / 2.2));
|
||||||
|
qgl_FragData[0].rgb = retColor;
|
||||||
|
}
|
||||||
6
qglview/shaders/hdr.vert
Normal file
6
qglview/shaders/hdr.vert
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
#version 150
|
||||||
|
|
||||||
|
void main(void) {
|
||||||
|
qgl_FragTexture = qgl_Texture;
|
||||||
|
gl_Position = qgl_ftransform();
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user