Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Z-fighting / dept buffer glitches in equidistant mode #1

Open
johanjohan opened this issue Feb 14, 2020 · 12 comments
Open

Z-fighting / dept buffer glitches in equidistant mode #1

johanjohan opened this issue Feb 14, 2020 · 12 comments

Comments

@johanjohan
Copy link

Hi @hiroMTB , thank you for this very usable addon. I realize some depthbuffer glitches in TRIANGLE_SHADER mode when I draw ofBoxPrimitives for testing. Could you recommend a method to get rid of these glitches? So far I was only trying wth near/far clipping planes with no change at all.

I use
glEnable(GL_DEPTH_TEST);
glClear(GL_DEPTH_BUFFER_BIT);
glDepthFunc(GL_LESS);

BTW it works on windows10 OF 0.11.0

@hiroMTB
Copy link
Owner

hiroMTB commented Feb 14, 2020

Hello, thank you for yojr feedback!
Can you share example image?

@johanjohan
Copy link
Author

sure!

2020-02-14-23-20-24-973

@hiroMTB
Copy link
Owner

hiroMTB commented Feb 15, 2020

Why do you do glClear(GL_DEPTH_BUFFER_BIT)?

@johanjohan
Copy link
Author

glClear(GL_DEPTH_BUFFER_BIT) is part of the attempts to improve on the z-fighting. the result is identical without. I can comment it out without change

@hiroMTB
Copy link
Owner

hiroMTB commented Feb 15, 2020 via email

@johanjohan
Copy link
Author

strange...I only added the 3 lines after seeing the glitches, i see no difference in windows10

.h file almost identical

#pragma once

#include "ofMain.h"
#include "ofxEquidistantProjection.h"
#include "ofxGui.h"

using namespace ofxequidistantprojection;
using namespace glm;

class ofApp: public ofBaseApp{
	public:
		void setup();
		void update();
		void draw();
		void keyPressed(int key);
		
        void begin(ShaderType type);
        void end(ShaderType type);
        
        ofxEquidistantProjection proj;
    
        ofSpherePrimitive sphere;
        ofEasyCam normalCam;
    
        ofxPanel gui;
        ofxLabel fps;
        ofParameterGroup prm;
        ofParameter<bool> bEqui;
        ofParameter<bool> bDraw2dGuide;
        ofParameter<bool> bDraw3dGuide;
        ofParameter<bool> bDrawPoints;
        ofParameter<bool> bDrawLines;
        ofParameter<bool> bDrawTriangles;
    
        ofParameter<glm::vec3> objPos;
        ofParameter<float> objScale;
        
        ofVboMesh vboPoints;
        ofVboMesh vboLines;

		const static int windowSize;

};

.cpp

#include "ofApp.h"

using namespace glm;

const int ofApp::windowSize = 1024;


struct Obj {

	glm::vec3		p;
	ofColor			c;
	float			s;
	ofBoxPrimitive	box;

	Obj() : p(0, 0, 0), c(ofColor::red), s(1) {
		box.setUseVbo(true);
	}

	void randomizePosSize() {
		s = ofRandom(0.1, 1.0);

		const float d = 7.0 / 3; // 7.0
		p = glm::vec3(
			ofRandom(-d, +d),
			ofRandom(-d, +d),
			ofRandom(-d, +d)
		);
		box.set(s, s, s);
		box.setPosition(p);
	}

	void addColors(const ofColor &_c) {
		vector<vec3> & vs = box.getMesh().getVertices();
		for (int i = 0; i < vs.size(); i++) {
			box.getMesh().addColor(_c);
		}
		box.enableColors();
	}

	void update(const float &_e11) {
		const float d = 3.0;
		box.setPosition(
			p + glm::vec3(
				ofMap(_e11, -1, +1, -d, +d),
				ofMap(_e11, -1, +1, -d, +d),
				ofMap(_e11, -1, +1, -d, +d)
			)
		);
	}
};
vector<Obj> objects;
const size_t numObjs = 100;


void ofApp::setup() {
	ofBackground(0);
	ofSetColor(255);
	ofSetCircleResolution(50);
	ofSetFrameRate(2000);
	ofSetVerticalSync(false);
	ofSeedRandom(123);

	proj.setup();
	proj.getCamera().setPosition(0, 0, 0);
	proj.getCamera().setNearClip(0.01); // 0.01 no change...
	proj.getCamera().setFarClip(1000); // 1000

	normalCam.setNearClip(0.01); // 0.01
	normalCam.setFarClip(1000);
	normalCam.setDistance(10);
	//normalCam.disableMouseInput();

	gui.setup();
	prm.add(bEqui.set("Equidistant Projection", true));
	prm.add(bDraw2dGuide.set("Draw 2D Guide", false));
	prm.add(bDraw3dGuide.set("Draw 3D Guide", false));
	prm.add(bDrawPoints.set("Draw Points", false));
	prm.add(bDrawLines.set("Draw Lines", false));
	prm.add(bDrawTriangles.set("Draw Triangles", true));

	prm.add(objPos.set("Object Position", vec3(0, 0, 0), vec3(-200, -200, -20), vec3(200, 200, 20)));
	prm.add(objScale.set("Object Scale", 1, 0, 10.0));
	gui.add(fps.setup("fps", "0"));
	gui.add(prm);

	vboPoints.setMode(OF_PRIMITIVE_POINTS);
	for (int i = 0; i < 100; i++) {
		vboPoints.addColor(ofColor(255, 255, 255));
		vboPoints.addVertex(vec3(ofRandom(-2, 2), ofRandom(-2, 2), ofRandom(-2, 2)));
	}

	vboLines.setMode(OF_PRIMITIVE_LINES);
	for (int i = 0; i < 100; i++) {
		vboLines.addColor(ofColor(255, 255, 255));
		vboLines.addVertex(vec3(ofRandom(-2, 2), ofRandom(-2, 2), ofRandom(-2, 2)));
	}

	sphere.setUseVbo(true); // ????
	sphere.setRadius(10);
	sphere.setResolution(10); // 10
	sphere.setPosition(0, 0, 0);
	sphere.setOrientation(ofVec3f(90, 0, 0));
	vector<vec3> & vs = sphere.getMesh().getVertices();

#if 0
	for (int i = 0; i < vs.size(); i++) {
		sphere.getMesh().addColor(ofFloatColor(1, 1, 1, 1));
	}
#else
	// 3j
	for (int i = 0; i < vs.size(); i++) {
		float angle = ofMap(i, 0, vs.size() - 1, 0, 270);
		ofColor col = ofColor::red;
		col.setHueAngle(angle);
		sphere.getMesh().addColor(col);
	}
#endif

	// 3j
	for (int i = 0; i < numObjs; i++) {
		Obj tmp;
		tmp.c = ofColor::red;
		tmp.c.setHueAngle(ofMap(i, 0, numObjs - 1, 0, 270));
		tmp.randomizePosSize();
		tmp.addColors(tmp.c);
		objects.push_back(tmp);
	}

	//GLint depthBits;
	//glGetIntegerv(GL_DEPTH_BITS, &depthBits);
	//ofLogNotice(__FUNCTION__) << "depthBits: " << depthBits;
}

void ofApp::update() {
	fps = ofToString(ofGetFrameRate());

	for (int i = 0; i < objects.size(); i++) {
		objects[i].update(
			sinf(ofGetElapsedTimef() / (i + 1) / (objects.size() / 44.f) )
		); 
	}
}

void ofApp::begin(ShaderType type) {
	ofPushMatrix();
	bEqui ? proj.begin(type) : normalCam.begin();
	ofDrawAxis(10);
	ofTranslate(objPos);
	ofScale(objScale, objScale, objScale);
}

void ofApp::end(ShaderType type) {
	bEqui ? proj.end(type) : normalCam.end();
	ofPopMatrix();
}

void ofApp::draw() {

	ofBackground(150);

	if (bDrawPoints) {
		glPointSize(3);
		begin(ShaderType::POINT_SHADER);
		ofSetColor(255);
		glColor4f(255, 255, 255, 255);
		vboPoints.draw();
		sphere.getMesh().setMode(OF_PRIMITIVE_POINTS);
		sphere.draw(OF_MESH_POINTS);
		end(ShaderType::POINT_SHADER);
	}

	if (bDrawLines) {
		begin(ShaderType::LINE_SHADER);
		ofSetColor(255);
		vboLines.draw();

		if (bDraw3dGuide) {
			ofNoFill();
			ofSetColor(0, 0, 255);
			proj.drawEquidistantHemisphere(10);
		}
		end(ShaderType::LINE_SHADER);
	}

	if (bDrawTriangles) {
		begin(ShaderType::TRIANGLE_SHADER);
		ofSetColor(255);
		sphere.getMesh().setMode(OF_PRIMITIVE_TRIANGLES);
		sphere.drawWireframe();
		end(ShaderType::TRIANGLE_SHADER);
	}


	if (bDraw2dGuide) {
		ofPushMatrix();
		ofSetupScreenOrtho();
		ofTranslate(ofGetWidth() / 2, ofGetHeight() / 2);
		ofSetColor(0, 255, 0);
		ofNoFill();
		proj.draw2dCircles(ofGetWidth() / 2);
		ofPopMatrix();
	}

	// https://learnopengl.com/Advanced-OpenGL/Depth-testing
	// some Z-fighting
	if (true)
	{
		const ShaderType shadertype = ShaderType::TRIANGLE_SHADER; // TRIANGLE_SHADER
		glEnable(GL_DEPTH_TEST);
		//glDepthFunc(GL_LESS);
		//glClear(GL_DEPTH_BUFFER_BIT);
		begin(shadertype);
		//ofEnableDepthTest();
		for (int i = 0; i < objects.size(); i++) {
			objects[i].box.draw(); 
		}
		end(shadertype);
	}


	ofSetupScreenOrtho();
	ofDisableDepthTest();
	gui.draw();
}


void ofApp::keyPressed(int key) {

	if (key == 's'){
		ofSaveScreen("_snaps/" + ofGetTimestampString() + ".png");
	}
}

main

#include "ofApp.h"

int main(){
	
	ofGLFWWindowSettings settings;
	settings.multiMonitorFullScreen = true;
	settings.setGLVersion(3,2);
    settings.setSize(ofApp::windowSize, ofApp::windowSize);
	//settings.setPosition(vec2(0,-1080));
	settings.setPosition(vec2(0,0));
	ofCreateWindow(settings);
    
	// this kicks off the running of my app
	// can be OF_WINDOW or OF_FULLSCREEN
	// pass in width and height too:
	ofRunApp(new ofApp());
}

lots of glitches, all looking good in normal camera mode

2020-02-16-01-15-13-803

@hiroMTB
Copy link
Owner

hiroMTB commented Feb 21, 2020

Thanks!
I'm seeing the same issue on macOS.
And I can fix by commenting out glEnable(GL_DEPTH_TEST)
Hope it works on Windows too.

@johanjohan
Copy link
Author

johanjohan commented Feb 22, 2020

@hiroMTB yes, this works, but then the depth order is not correctly displayed, which is an issue for my case. I guess, the only solution will be to z-sort all objects before drawing, do you agree? Still, would have been so much better and probably faster to fix that in the shader if possible.
btw, your addon is very useful, fast and good quality. Thank you.

@hiroMTB
Copy link
Owner

hiroMTB commented Feb 22, 2020

I see.
In the triangle shader, I populated additional triangles in order to increase precision.
But I didnt calculate gl_Normal for each triangle. This might be the issue.

Here is the code.
https://github.com/hiroMTB/ofxEquidistantProjection/blob/master/example/bin/data/shadersGL3/tri.geom

You can see that GenerateTriangle() is called 4 times at the bottom. It means splitting the original triangle to 4 smaller triangles (subdivide). It might be okay to copy original normal and use for 4 subdivided triangles. But probably we need to apply equidistant projection to normal calculation too. It must be not so difficult. I think we can calculate like following way.

  1. calculate starting point of normal (center of subdivided triangle)
  2. calculate end point of normal (center + original normal)
  3. apply equidistant conversion to 1 and 2. Result 1' and 2'
  4. 2' - 1' = new normal

I'm not sure. It might be completely different reason.

@johanjohan
Copy link
Author

@hiroMTB thank you. Are you going to give your fix-suggestion a try?

@hiroMTB
Copy link
Owner

hiroMTB commented Mar 3, 2020 via email

@johanjohan
Copy link
Author

great, keep me posted

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants