Käytän OpenGL:ää eräissä projekteissani kaksiulotteisen grafiikan piirtämiseen, ja sinänsä homma kyllä toimii, pienen bugin säestämänä. Kun luon ikkunan ja asetan OpenGL:n projektiot, niin (0, 0) ja (ikkunan_leveys, ikkunan_korkeus) koordinaatit heittävät yhdellä pikselillä. Eli jos piirrän kohtaan (0, 0) punaisen pikselin, se ei näy vaan on siirtynyt yhden pikselin verran ylöspäin, pois näytöstä, eli jos piirrän sen kohtaan (0, 1) niin se näkyy (ei siis virhettä vaakakoordinaatissa). Jos haluan (ikkunan_leveys, ikkunan_korkeus) kohtaan pikselin, sekään ei näy vaan nyt täytyy x-koordinaatista vähentää yksi pikseli. Mielelläni haluaisin että koko näytön alueella olisi täsmällinen pikselitarkkuus ja alkukohta olisi (0, 0) jne.
Tässä vähän koodia:
glfwInit(); // Alustetaan GLFW glfwOpenWindowHint(GLFW_FSAA_SAMPLES, 0); // Ei reunanpehmennystä glfwOpenWindowHint(GLFW_WINDOW_NO_RESIZE, GL_TRUE); // Ikkunan kokoa ei voi muuttaa if (!glfwOpenWindow(WIDTH, HEIGHT, 8, 8, 8, 0, 0, 0, GLFW_FULLSCREEN)) // Onnistuuko ikkunan luonti { glfwTerminate(); exit(EXIT_FAILURE); } ... glViewport(0, 0, WIDTH, HEIGHT); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(0, WIDTH, HEIGHT, 0); glMatrixMode(GL_MODELVIEW); glLoadIdentity();
EDIT: Seuraan huvittuneena minkä otsikon moderaattori päättää jättää lopulliseksi. Ei kai siinä, omani kieltämättä oli huono.
Nyt kannattaa muistaa tällainen mielenkiintoinen asia, että OpenGL:n koordinaatisto on tosiaan matemaattinen eikä pikselipohjainen. Jos siis ikkunan vasen alakulma on kohdassa (0, 0), tämä tosiaan tarkoittaa vasemman alakulman pikselin vasenta alakulmaa. Pikselin keskikohta sen sijaan on kohdassa (0,5, 0,5), jos koordinaatiston yksikkö vastaa pikseliä. Olet poistanut antialiasoinnin käytöstä, joten OpenGL arpoo jollakin sumealla logiikalla (luultavasti sen mukaan, miten nyt liukuluku sattuu pyöristymään) jonkin pyydettyä koordinaattia ympäröivistä neljästä pikseleistä, sinun huonoksi onneksesi ilmeisesti sen ruudun ulkopuolelle jäävän.
Ohjelma ehkä toimii haluamallasi tavalla, jos vähennät kaikista glOrthon koordinaateista puolikkaan, jolloin koordinaatit (0, 0) ja (W-1, H-1) osuvat vastaavien kulmapikselien keskelle. En kuitenkaan mene asiasta takuuseen, sen verran vähän olen asiaan perehtynyt. :)
Tämä tosiaankin on ollut tiedossa, mutta kuvittelisin että pikselitarkkuuteen olisi silti jotenkin mahdollista päästä. Kokeilin tuon puolikkaan vähentämistä, mutta siltikään pikselit eivät mene aivan täysin oikein. Onko OpenGL:ssä joitain funktioita joilla voitaisiin muuttaa sen suhtautumista pikselin valintaan?
EDIT: Ei, kyllä se silti näyttäisi toimivan, unohdin vähentää puolikkaan myös right ja bottom parametreista. Nyt näyttää siis tältä ja ainakin pikaisella testauksella toimii pikselintarkasti:
gluOrtho2D(-0.5, WIDTH-0.5, HEIGHT-0.5, -0.5);
Hei!
Eikös gl myöskin pitänyt vastaavan käskyn.
mitäs eroa on käyttää glu taikka gl orthoa ??
siis muuta kuin että toinen on gl ja toinen glu ;)
onko toiminnallisia eroja ??
gl.glViewport(0, 0, width, height); gl.glMatrixMode(GL.GL_PROJECTION); gl.glLoadIdentity(); gl.glOrtho( -(width/2),width/2,-(height/2),height/2,20f,-20f ); gl.glMatrixMode(GL.GL_MODELVIEW); gl.glLoadIdentity();
vain syvyys ??
minä elän käsityksessä, että, jos ei tarvitse glulookat() käskyä.
niin käytän aina tuota gl orthoa. ei tarvitse new glu() käskyä pienissä projekteissani.
( en tosin tunnekkaan kaikki glu ominaisuuksia, käytän sitä siis vain glulookat() kanssa )
//----
kiitos,,
OpenGL manual kirjoitti:
gluOrtho2D sets up a two-dimensional orthographic viewing region. This is equivalent to calling glOrtho with near=-1 and far=1.
Voisit ehkä ottaa asioista itsekin selvää, ennen kuin lähettelet aiheeseen liittymättömiä viestejä, vai mitä?
Pistän tämän pätkän jällen kerran näkyville.
Eli pikselintarkka 2d opengl:ssä
const int width = ruudun_leveys_x; const int height = ruudun_leveys_y; glMatrixMode( GL_PROJECTION ); glLoadIdentity(); gluOrtho2D( 0, width, height, 0 ); glMatrixMode( GL_MODELVIEW ); glLoadIdentity(); glTranslatef( 0.375, 0.375, 0.0 );
Miksi toimii?
viimeinen glTranslatef() siirtää koordinaatteja sen verran että koordinaatiston pisteet siirtyvät ikään kuin "pikselien keskelle" ja rasteroituvat pikselin tarkkuudella.
Tuo perus-modelview-matriisi (missä pikseleitä offsetattu tuo 0.375 yksikköä) pitää sitten muistaa säilyttää koko 2d-rasteroinnin ajan, eli jos teet jotain muita matriisioperaatioita modelview-matriisilla muista tallettaa tuo perusmodelview glPushMatrix() ja palauttaa glPopMatrix() kutsuilla.
Onko sillä väliä siirtääkö modelview matriisia tuon 0.375 vai asettaako orthoon nuo edellämainitut arvot (vai pitäisikö laittaa sinnekin 0.375? Mistä se tulee)?
Ei ole tietääkseni mitään (ainakaan speksiin tai muuhun selvään auktoriteettiin nojautuvaa) perustetta, miksi juuri 0.375 pitäisi asettaa. Sen sijaan tietääkseni on hyviä perusteita, miksi juuri 0.5 on oikein (kuten selitin). Lopputulos on kuitenkin näennäisesti sama kokonaisluvuilla pelattaessa, koska kummassakin saatu liukuluku osuu oikean pikselin alueelle. Minusta on myös järkevämpää ja loogisempaa asettaa tuo suoraan perspektiiviin, koska sitähän sillä on tarkoitus säätää eikä tarvitse huolehtia matriisin tallentamisesta ja palauttamisesta. Heppoisia perusteita pieslicen tavalle (glTranslate) löytyy, jos samaan kuvaan on tarkoitus piirtää myös muuta kuin pikseligrafiikkaa.
Toki saa valaista asiaa, jos tuossa on jotain aivan erityisen hienoa ja oikeaa. ^^
Onko varmaa että 0.5 pitäisi vähentää? Yläkulman pikselin jos piirtää quadina niin se olisi 0,0 - 1,1. Olen olettanut että 0,0 tarkoittaa sen kulmapikselin nurkkaa. Mutta se vaihtelee näytönohjaimittain hieman, ainakin vanhoissa.
Tietty kun ikkunan kanssa on tekemisissä niin on otettava huomioon mitä leveys/korkeus muuttujia käyttää. Ikkunan leveys ja korkeus muuttujat saattaa kattaa reunat ja otsikkorivin.
Tumpelo kirjoitti:
Onko sillä väliä siirtääkö modelview matriisia tuon 0.375 vai asettaako orthoon nuo edellämainitut arvot (vai pitäisikö laittaa sinnekin 0.375? Mistä se tulee)?
Tuo 0.375 oli mainittu jossain opengl-tutoriaalissa vuonna kivi, se on sellainen "tried and true"-arvo. Eli siirtää juuri sen verran että se virtuaalirasteroija menee "pikselin keskelle". Joissain tapauksissa tuo 0.5 saattaa pyöristyä yli "pikselin keskeltä" ja rasteroiutua yhden pikselin vinoon.
Hankala kuvailla.
Aihe on jo aika vanha, joten et voi enää vastata siihen.